版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第C語言實現(xiàn)三子棋游戲的示例代碼目錄1.前言2.準備工作3.使用二維數(shù)組存儲下棋的數(shù)據(jù)4.初始化棋盤為全空格5.打印棋盤6.玩家下棋7.電腦下棋8.判斷輸贏9.效果展示10.完整代碼game.hgame.ctest.c
1.前言
大家好,我是努力學習游泳的魚,今天我們會用C語言實現(xiàn)三子棋。所謂三子棋,就是三行三列的棋盤,玩家可以和電腦下棋,率先連成三個的獲勝。話不多說,我們開始吧。
2.準備工作
我們可以在一個項目中創(chuàng)建三個文件,分別是:
test.c,測試游戲的邏輯。game.c,游戲的實現(xiàn)。game.h,函數(shù)聲明,符號的定義。
測試這個游戲時,我們玩一把肯定不過癮,所以需要使用dowhile循環(huán),每次可以選擇繼續(xù)玩或者退出游戲。先把大致的框架搭出來。
#includestdio.h
voidmenu()
printf("****************************\n");
printf("********1.play******\n");
printf("********0.exit******\n");
printf("****************************\n");
intmain()
intinput=0;
menu();
printf("請選擇(1/0):
scanf("%d",input);
switch(input)
case1:
printf("三子棋\n");
break;
case0:
printf("退出游戲\n");
break;
default:
printf("選擇錯誤\n");
break;
}while(input);
return0;
當然,我們的游戲不可能只是打印三子棋這三個字這么簡單,具體的實現(xiàn)我們會封裝成一個函數(shù),暫且取名為game。
3.使用二維數(shù)組存儲下棋的數(shù)據(jù)
當我們下三子棋的時候,需要把下棋的數(shù)據(jù)存起來。由于三子棋的棋盤是33的,我們就需要一個三行三列的數(shù)組來存儲下棋的數(shù)據(jù)。charboard[3][3]={0};
4.初始化棋盤為全空格
當我們還沒開始下棋時,棋盤上應該啥都沒有,但是真的是啥都沒有嗎?事實上,如果我們打印棋盤時,能打印出沒有棋子的效果,數(shù)組里應該是全空格。所以,我們需要寫一個函數(shù),初始化棋盤為全空格。InitBoard(board,3,3);這個函數(shù)的聲明,我們會放在game.h里。具體的實現(xiàn),我們會放在game.c里。以下的函數(shù)同理。該函數(shù)的聲明:voidInitBoard(charboard[3][3],introw,intcol);(以下的函數(shù)均省略聲明)。該函數(shù)的實現(xiàn),只需遍歷這個二維數(shù)組,全部賦值為空格。
voidInitBoard(charboard[3][3],introw,intcol)
inti=0;
for(;irow;++i)
intj=0;
for(;jcol;++j)
board[i][j]='';
有沒有發(fā)現(xiàn),這個程序中,到處都要用到數(shù)組三行三列這個特點。如果我們想要改變這一點,比如改成五行五列,就需要改很多地方,非常麻煩。怎么解決這個問題呢?我們可以在game.h里定義兩個常量ROW和COL,這樣每次只需要改變#define后的值就行了。
#defineROW3
#defineCOL3
這樣以上出現(xiàn)的所有3都可以用ROW和COL替代了(此處省略)。注意:如果想使用game.h里的符號,我們需要在game.c和test.c里引用這個頭文件。引用自己寫的頭文件要用雙引號。#includegame.h而對于其他頭文件如stdio.h,我們不需要在game.c和test.c里包含兩次,只需在game.h里包含就行了。
5.打印棋盤
我們初始化棋盤后,會想要看一看棋盤長啥樣,所以接下來寫一個打印棋盤的函數(shù)DisplayBoard(board,ROW,COL);
如果你認為打印出數(shù)組的數(shù)據(jù)就行了,從而這樣寫:
voidDisplayBoard(charboard[ROW][COL],introw,intcol)
inti=0;
for(;irow;++i)
intj=0;
for(;jcol;++j)
printf("%c",board[i][j]);
printf("\n");
實際運行時,你會發(fā)現(xiàn),打印了,但沒完全打印。
事實上,此時打印的是一堆空格,非常難看。如果我們想打印得好看點,可以考慮加上一些橫向和豎向的分割。比如我設想了這樣一種打印的效果:
||
---|---|---
||
---|---|---
||
假設把
||
---|---|---
當成一組,總共需要打印3組,為什么呢?因為有3行。
每一組里面,又分為數(shù)據(jù)行和分割行。我們需要先打印數(shù)據(jù)行,再打印分割行。
||//數(shù)據(jù)行
---|---|---//分割行
所以一個簡單的想法是這么寫:
voidDisplayBoard(charboard[ROW][COL],introw,intcol)
inti=0;
for(;irow;++i)
//打印數(shù)據(jù)
printf("%c|%c|%c\n",board[i][0],board[i][1],board[i][2]);
//打印分割的行
printf("---|---|---\n");
效果如下:
我們發(fā)現(xiàn)多打印了一行分割行,所以打印分割行時要加一條判斷,不是最后一行才打印分割行。
if(irow-1)
printf("---|---|---\n");
這樣子打印就好看多了。
但是這么寫的話,就相當于,一行一定要打印3列,后面就沒有改變的可能了。比如我把ROW和COL都改成5,效果如下:
所以這種寫法還是不夠好。最好的寫法是,再用一層循環(huán)控制列的打印。比如對于數(shù)據(jù)行:
||
我們可以把
|
當成一組數(shù)據(jù),打印三組,最后一組就不用加上|了(同上一種寫法用一個if語句來控制)。
對于分割行
---|---|---
我們可以把
---|
當成一組數(shù)據(jù),打印三組,最后一組就不用加上|了(還是用if語句來控制)。
實現(xiàn)如下:
voidDisplayBoard(charboard[ROW][COL],introw,intcol)
inti=0;
for(;irow;++i)
//打印數(shù)據(jù)
intj=0;
for(;jcol;++j)
printf("%c",board[i][j]);
if(jcol-1)
printf("|");
printf("\n");
//打印分割的行
if(irow-1)
for(j=0;jcol;++j)
printf("---");
if(jcol-1)
printf("|");
printf("\n");
效果也沒問題:
若把ROW和COL改成10,打印出來的效果如下:
這樣寫出來的代碼就比較通用,具有比較強的可維護性。
6.玩家下棋
接下來寫玩家下棋的函數(shù)。player_move(board,ROW,COL);
先讓玩家輸入坐標,若x和y都在1到3之間,則輸入的坐標合法,在數(shù)組對應的位置是board[x-1][y-1],若該位置仍然是空格,則這個位置沒有被下過,就把數(shù)組的這個元素改成*。由于若玩家輸入的坐標非法或者被占用時,需要重新輸入,故需要一個循環(huán)。
voidplayer_move(charboard[ROW][COL],introw,intcol)
intx=0;
inty=0;
printf("玩家下棋\n");
while(1)
printf("請輸入坐標:
scanf("%d%d",x,
if(x=1x=rowy=1y=col)
//下棋
if(board[x-1][y-1]=='')
board[x-1][y-1]='*';
break;
else
printf("該坐標被占用,請重新輸入\n");
else
printf("坐標非法,請重新輸入\n");
玩家下棋后再把棋盤打印一下DisplayBoard(board,ROW,COL);效果如下:
7.電腦下棋
玩家下完棋后就輪到電腦下棋computer_move(board,ROW,COL);
我們讓電腦隨機下棋,只需生成兩個隨機的坐標x和y,若該位置是空格,就下在這個位置,如果是空格,那就再次產生隨機坐標,可見,這也需要一個循環(huán)來實現(xiàn)。
voidcomputer_move(charboard[ROW][COL],introw,intcol)
intx=0;
inty=0;
printf("電腦下棋\n");
while(1)
x=rand()%row;//0~2
y=rand()%col;//0~2
if(board[x][y]=='')
board[x][y]='#';
break;
使用rand函數(shù)前需要使用srand函數(shù)來設置隨機數(shù)生成器的起點。我們需要給srand函數(shù)傳一個時間戳,這就要用到time函數(shù)。srand((unsignedint)time(NULL));使用rand和srand都需要引用頭文件stdlib.h,使用time函數(shù)需要引用頭文件time.h。
我們用一個循環(huán),就能實現(xiàn)玩家和電腦輪流下棋的效果。
while(1)
//玩家下棋
player_move(board,ROW,COL);
DisplayBoard(board,ROW,COL);
//電腦下棋
computer_move(board,ROW,COL);//隨機下棋
DisplayBoard(board,ROW,COL);
8.判斷輸贏
什么時候游戲就結束了呢?如果玩家贏了,或者電腦贏了,或者平局,游戲就結束了,否則游戲繼續(xù)。
我們來設計一個is_win函數(shù)來判斷棋局是上面四種狀態(tài)的哪一種。我們這么設計is_win函數(shù)的返回值:
玩家贏-*電腦贏-#平局-Q繼續(xù)-C
當棋局狀態(tài)不是C時說明游戲結束了,就跳出循環(huán),接著根據(jù)不同情況打印不同的結果。
charret=0;
while(1)
//玩家下棋
player_move(board,ROW,COL);
DisplayBoard(board,ROW,COL);
//判斷輸贏
ret=is_win(board,ROW,COL);
if(ret!='C')
break;
//電腦下棋
computer_move(board,ROW,COL);//隨機下棋
DisplayBoard(board,ROW,COL);
ret=is_win(board,ROW,COL);
if(ret!='C')
break;
if(ret=='*')
printf("玩家贏\n");
elseif(ret=='#')
printf("電腦贏\n");
printf("平局\n");
如何實現(xiàn)is_win函數(shù)呢?只需判斷每行,每列,每條對角線是否有三個同樣的棋子就行了。
先判斷行(由于玩家贏和電腦贏都是返回對應的棋子*和#,所以直接把對應的數(shù)組元素返回就行了。):
inti=0;
for(;irow;++i)
if(board[i][0]==board[i][1]board[i][1]==board[i][2]board[i][1]!='')
returnboard[i][1];
判斷列同理:
for(i=0;icol;++i)
if(board[0][i]==board[1][i]board[1][i]==board[2][i]board[1][i]!='')
returnboard[1][i];
最后判斷對角線:
if(board[0][0]==board[1][1]board[1][1]==board[2][2]board[1][1]!='')
returnboard[1][1];
if(board[0][2]==board[1][1]board[1][1]==board[2][0]board[1][1]!='')
returnboard[1][1];
如果有人贏了,在前面的代碼中就會返回。如果沒人贏,再來判斷是否平局。如果棋盤沒有空格了,那就是平局。我們可以寫一個is_full函數(shù)來判斷棋盤是否滿了。如果滿了就返回1,沒滿就返回0。
由于is_full函數(shù)只是寫給is_win函數(shù)的,只需要在game.c這個文件內使用,所以加上static。具體的實現(xiàn),只需要遍歷數(shù)組,若發(fā)現(xiàn)空格,說明棋盤沒滿,就返回0,否則返回1。
而如果沒人贏,也不是平局,則游戲繼續(xù),returnC即可。
9.效果展示
寫到這,我們就把三子棋程序寫完啦。接下來看看效果:
玩家贏:
電腦贏:
平局:
10.完整代碼
下面是完整的代碼:
game.h
#pragmaonce
#includestdio.h
#includestdlib.h
#includetime.h
#defineROW3
#defineCOL3
//初始化棋盤
voidInitBoard(charboard[ROW][COL],introw,intcol);
//打印棋盤
voidDisplayBoard(charboard[ROW][COL],introw,intcol);
//玩家下棋
voidplayer_move(charboard[ROW][COL],introw,intcol);
//電腦下棋
voidcomputer_move(charboard[ROW][COL],introw,intcol);
//判斷輸贏
charis_win(charboard[ROW][COL],introw,intcol);
game.c
#define_CRT_SECURE_NO_WARNINGS1
#include"game.h"
voidInitBoard(charboard[ROW][COL],introw,intcol)
inti=0;
for(;irow;++i)
intj=0;
for(;jcol;++j)
board[i][j]='';
//voidDisplayBoard(charboard[ROW][COL],introw,intcol)
//inti=0;
//for(;irow;++i)
//intj=0;
//for(;jcol;++j)
//printf("%c",board[i][j]);
//printf("\n");
//voidDisplayBoard(charboard[ROW][COL],introw,intcol)
//inti=0;
//for(;irow;++i)
////打印數(shù)據(jù)
//printf("%c|%c|%c\n",board[i][0],board[i][1],board[i][2]);
////打印分割的行
//if(irow-1)
//printf("---|---|---\n");
voidDisplayBoard(charboard[ROW][COL],introw,intcol)
inti=0;
for(;irow;++i)
//打印數(shù)據(jù)
intj=0;
for(;jcol;++j)
printf("%c",board[i][j]);
if(jcol-1)
printf("|");
printf("\n");
//打印分割的行
if(irow-1)
for(j=0;jcol;++j)
printf("---");
if(jcol-1)
printf("|");
printf("\n");
voidplayer_move(charboard[ROW][COL],introw,intcol)
intx=0;
inty=0;
printf("玩家下棋\n");
while(1)
printf("請輸入坐標:
scanf("%d%d",x,
if(x=1x=rowy=1y=col)
//下棋
if(board[x-1][y-1]=='')
board[x-1][y-1]='*';
break;
else
printf("該坐標被占用,請重新輸入\n");
else
printf("坐標非法,請重新輸入\n");
voidcomputer_move(charboard[ROW][COL],introw,intcol)
intx=0;
inty=0;
printf("電腦下棋\n");
while(1)
x=rand()%row;//0~2
y=rand()%col;//0~2
if(board[x][y]=='')
board[x][y]='#';
break;
staticintis_full(charboard[ROW][COL],introw,intcol)
inti=0;
for(;irow;++i)
intj=0;
for(;jcol;++j)
if(board[i][j]=='')
return0;//沒有滿
return1;//滿了
charis_win(charboard[ROW][COL],introw,intcol)
inti=0;
//判斷行
for(;irow;++i)
if(board[i][0]==board[i][1]board[i][1]==board[i][2]board[i][1]!='')
returnboard[i][1];
//判斷列
for(i=0;icol;++i)
if(board[0][i]==board[1][i]board[1][i]==board[2][i]board[1][i]!='')
returnboard[1][i];
//對角線
if(board[0][0]==board[1][1]board[1][1]==board[2][2]board[1][1]!='')
returnboard[1][1];
if(board[0][2]==board[1][1]board[1][1]==board[2][0]board[1][1]!='')
returnboard[1][1];
//判斷平局
if(is_full(board,row,col)==1)
return'Q';
//繼續(xù)
return'C';
test.c
#define_CRT_SECURE_NO_WARNINGS1
#include"game.h"
voidmenu()
printf("****************************\n");
printf("********1.play******\n");
printf("********0.exit******\n");
printf
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026廣東惠州市博羅縣中小企業(yè)發(fā)展事務中心招聘編外人員1人備考題庫含答案詳解
- 食品不合格食品處置制度
- 2026江西吉安市新供商貿物流有限公司招募就業(yè)見習人員2人備考題庫及答案詳解參考
- 罕見腫瘤的個體化治療藥物相互作用管理策略與決策-3
- 2026江西安源路橋集團有限公司外聘人員招聘2人備考題庫有答案詳解
- 2026廣西百色市事業(yè)單位招聘1563人備考題庫有答案詳解
- 罕見腫瘤的個體化治療生活質量干預措施與心理需求
- 少兒培訓財務制度
- 砂石礦財務制度
- 建筑工程業(yè)財務制度
- 2026年維修工崗位面試題庫含答案
- 2026年溫州市1.5模高三語文試題作文題目解析及3篇范文:打扮自己與打扮大地
- 2026年湘西民族職業(yè)技術學院單招職業(yè)技能筆試參考題庫含答案解析
- 2025-2026學年教科版(新教材)小學科學三年級下冊《昆蟲的一生》教學設計
- 2025年12月福建廈門市鷺江創(chuàng)新實驗室管理序列崗位招聘8人參考題庫附答案
- 化工工藝安全管理與操作手冊
- 規(guī)范外匯交易管理制度
- 高考英語讀后續(xù)寫技巧總結
- 2025年下半年河南鄭州市住房保障和房地產管理局招聘22名派遣制工作人員重點基礎提升(共500題)附帶答案詳解
- 維修事故協(xié)議書
- 2025ESC+EAS血脂管理指南要點解讀課件
評論
0/150
提交評論