200行C語言代碼實(shí)現(xiàn)簡易三子棋游戲

前言
三子棋應(yīng)該是是我們最早接觸到的棋類游戲,用C語言實(shí)現(xiàn)三子棋對初學(xué)者來說是一種不錯的鍛煉
編寫三子棋只需要用到數(shù)組、函數(shù)和生成隨機(jī)數(shù)的知識,所以比較適合成為編程學(xué)習(xí)者編寫的第一個小游戲。
一.代碼實(shí)現(xiàn)
第一部分是源碼復(fù)制就可以使用,每一個自定義函數(shù)在第二部分設(shè)計思路中都有詳細(xì)解釋,結(jié)合代碼實(shí)現(xiàn)和設(shè)計思路理解會有一個更好的效果
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 3
#define COL 3
void reset(char arr[ROW][COL])//將棋盤arr[ROW][COL]數(shù)據(jù)賦值為空格
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
arr[i][j] = ' ';
}
}
}
void dis_play(char arr[ROW][COL])//打印棋盤
{
for (int i = 0; i < ROW; i++)//for每一次進(jìn)去,打印一行數(shù)組和一條分割線
{ //數(shù)組行為:(空格)元素(空格)|(空格)元素(空格)|(空格)元素(空格)
//分割線為: - - - | - - - | - - -
for (int j = 0; j < COL; j++)//一行數(shù)組
{
printf(" %c ", arr[i][j]);
if (j < COL - 1)//為了美觀,最后的“|”不打印
{
printf("|");
}
}
printf("\n");
for (int k = 0; k < COL; k++)//一行分割線
{
printf("---");
if (k < COL - 1)//為了美觀,最后的“|”不打印
{
printf("|");
}
}
printf("\n");
}
}
void player_move(char arr[ROW][COL])//玩家下棋
{
int row = 0, col = 0;
while (1)
{
printf("玩家下棋,請輸入坐標(biāo)>:");
scanf("%d %d", &row, &col);
if (arr[row - 1][col - 1] == ' ')//判斷是否可以下棋
{
arr[row - 1][col - 1] = '*';
break;
}
printf("輸入錯誤,請再次輸入\n");
}
}
void computer_move(char arr[ROW][COL])//電腦下棋
{
int row = rand() % ROW;//生成行號
int col = rand() % COL;//生成列標(biāo)
printf("電腦下棋:>\n");
while (1)
{
if (arr[row][col] == ' ')//判斷是否可以下棋
{
arr[row][col] = '#';
break;
}
row = rand() % ROW;
col = rand() % COL;
}
}
int is_full(char arr[ROW][COL])//用于在is_win()中判斷是否為平局
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
if (arr[i][j] == ' ')
return 0;
}
}
return 1;
}
char is_win(char arr[ROW][COL])//三子棋勝利無非就三種情況:行相同、列相同和對角線相同。除開勝利還有平局
{
for (int i = 0; i < ROW; i++)//判斷行
{
if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ')
return arr[i][0];
}
for (int i = 0; i < COL; i++)//判斷列
{
if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ')
return arr[0][i];
}
//判斷對角線
if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[0][0] != ' ')
return arr[0][0];
if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[0][2] != ' ')
return arr[0][2];
//判斷平局
if (is_full(arr))
{
return 'q';
}
//都不滿足游戲繼續(xù)運(yùn)行 return ‘c'
return 'c';
}
void meau()
{
printf("------------------\n");
printf("| 1.play |\n");
printf("|----------------|\n");
printf("| 0.exit |\n");
printf("------------------\n");
}
void game()
{
char arr[ROW][COL];//初始化棋盤
char ch;
reset(arr);//將棋盤里每一個元素賦值為空格
dis_play(arr);
do
{
player_move(arr);
dis_play(arr);
ch=is_win(arr);
if (ch != 'c')
{
break;
}
computer_move(arr);
dis_play(arr);
ch=is_win(arr);
if (ch != 'c')
{
break;
}
} while (1);
switch (ch)//根據(jù)返回字符判斷結(jié)果
{
case '#':
printf("電腦勝利\n"); break;
case '*':
printf("玩家勝利\n"); break;
case 'q':
printf("平局\n"); break;
}
}
int main()
{
srand((unsigned)time(NULL));
int input = 0;
do
{
meau();
scanf("%d", &input);
switch (input)
{
case 1 :
game(); break;
case 0 :
break;
default :
printf("輸入錯誤\n");
}
} while (input);
return 0;
}二.設(shè)計思路
main()函數(shù)搭建框架
1.main()函數(shù)搭建框架:像所有的電腦游戲一樣,我們需要一個菜單,通過菜單選擇進(jìn)入游戲和退出游戲,當(dāng)一盤游戲結(jié)束時可以再次選擇進(jìn)入或者退出,菜單用printf()打印就可以解決,循環(huán)的進(jìn)入游戲用do while()循環(huán)就可以解決
實(shí)現(xiàn)代碼如下
void meau()
{
printf("------------------\n");
printf("| 1.play |\n");
printf("|----------------|\n");
printf("| 0.exit |\n");
printf("------------------\n");
}
void game()
{
·········
}
int main()
{
int input = 0;
do
{
meau();
scanf("%d", &input);
switch (input)
{
case 1 :
game(); break;
case 0 :
break;
default :
printf("輸入錯誤\n");
}
} while (input);
return 0;
}2.當(dāng)我們進(jìn)入case 1,運(yùn)行g(shù)ame()函數(shù);首先我們需要一個容器來存放我們的游戲數(shù)據(jù),此時創(chuàng)建字符二維數(shù)組arr[3][3]作為容器,玩家下的棋用“*”表示電腦用”#“表示。因為行和列都為3,后面經(jīng)常要使用,我們對他進(jìn)行宏定義一下
#define ROW 3 #define COL 3
dis_play( )函數(shù)
》.dis_play( ):我們下棋肯定需要棋盤來顯示我們的數(shù)據(jù),我們通過構(gòu)造一個函數(shù)dis_play()將數(shù)組打印出來來實(shí)現(xiàn)這一功能
dis_play()的功能其實(shí)就是把a(bǔ)rr[ROW][COL]以棋盤形式打印顯示出來,需要借助一些特殊字符”|“和”_“輔助打印
#define ROW 3 / 行:3
#define COL 3 / 列:3
void dis_play(char arr[ROW][COL])
{
for (int i=0;i<ROW;i++) /for每一次進(jìn)去,打印一行數(shù)組和一條分割線
{
for (int j = 0; j < COL; j++)//打印數(shù)組
{
printf(" %c ", arr[i][j]);
if (j < COL - 1)
{
printf("|");
}
}
printf("\n");
for (int k = 0; k < COL; k++)//打印分割線
{
printf("---");
if (k < COL - 1)
{
printf("|");
}
}
printf("\n");
}
}初步運(yùn)行代碼,打印棋盤:

reset ( )函數(shù)
》reset ( ) :我們下完一盤棋,還想下該怎么辦?這時候我們構(gòu)造一個函數(shù)reset(),將棋盤數(shù)組的每一個元素重置為空格
reset()函數(shù),遍歷數(shù)組,賦值為空格
void reset( char arr[ROW][COL])
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
arr[i][j] = ' ';//賦值空格
}
}
}player_move( )函數(shù)
》player_move( ):玩家下棋,不能隨便下,下過的地方不能下,我們構(gòu)造一個player_move()函數(shù)完成這一功能
player_move( )函數(shù)功能其實(shí)就是為數(shù)組arr[ROW][COL]賦值,數(shù)組元素為空格的地方就是可以下棋的地方
輸入坐標(biāo)時,和我們程序員思維不同,正常人認(rèn)為行是從1開始而不是從0開始,玩家輸入的數(shù)據(jù)需要減1才能正常賦值
void player_move(char arr[ROW][COL])
{
int row = 0, col = 0;
while (1)
{
printf("玩家下棋,請輸入坐標(biāo)>:");
scanf("%d %d", &row, &col);
if (arr[row-1][col-1] == ' ')
{
arr[row-1][col-1] = '*';
break;
}
printf("輸入錯誤,請再次輸入\n");
}
}玩家下棋

computer_move()函數(shù)
》computre_move()電腦下棋,為了更容易實(shí)現(xiàn)我們這里讓他再棋盤上隨機(jī)下,需要生成隨機(jī)數(shù)的知識,我們需要構(gòu)造一個函數(shù)
使用頭文件#include<stdlib.h>中的rand()函數(shù)可以生成一個0~32767的偽隨機(jī)數(shù),但使用rand()前先要使用srand()設(shè)置偽隨機(jī)數(shù)起點(diǎn)
起點(diǎn)只要寫一次,我們將srand((unsigned)time(NULL))定義在主函數(shù),此處是一種固定的寫法,time()函數(shù)需要引<time.h>頭文件將rand()%3即%ROW可以生產(chǎn)0、1、2這三個隨機(jī)數(shù),可以用來做數(shù)組的行號和列標(biāo)
int main()
{
srand((unsigned)time(NULL));/設(shè)置起點(diǎn)的固定寫法
int input = 0;
do
{
meau();
scanf("%d", &input);
switch (input)
{
case 1 :
game(); break;
case 0 :
break;
default :
printf("輸入錯誤\n");
}
} while (input);
return 0;
}
void computer_move(char arr[ROW][COL])
{
int row = rand() % ROW ;//利用隨機(jī)數(shù)生成行號列標(biāo)
int col = rand() % COL ;
printf("電腦下棋:>\n");
while (1)
{
if (arr[row][col] == ' ')//判斷是否為空格
{
arr[row][col] = '#';
break;
}
row = rand() % ROW;
col = rand() % COL;
}
}電腦下棋

is_win()函數(shù)
》is_win()光下棋也不行,每當(dāng)玩家或電腦下一步棋必須有東西來判斷到底是玩家贏了還是電腦贏了還是平局還是繼續(xù),我們構(gòu)造is_win()函數(shù)完成這一功能
is_win()函數(shù)功能最后是返回一個字符,電腦贏返回"#",玩家贏返回”*“,平局返回”q“,以上情況都不符合就返回”c“(continue)
三子棋勝利無非就三種情況:行相同、列相同和對角線相同我們用for和if語句就可以判斷
平局的情況其實(shí)就是棋盤滿了,我們構(gòu)造一個is_fuii()函數(shù),棋盤滿了,該函數(shù)返回1否則返回0;
int is_full(char arr[ROW][COL])
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
if (arr[i][j] == ' ')/棋盤還有空格則return 0
return 0;
}
}
return 1;
}
char is_win(char arr[ROW][COL]) /is_win()函數(shù)
{
for (int i = 0; i < ROW; i++)/判斷是否有行相同
{
if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ')
return arr[i][0];
}
for (int i = 0; i <COL; i++)/判斷是否有列相同
{
if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ')
return arr[0][i];
}
/判斷對角線是否相同
if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[0][0] != ' ')
return arr[0][0];
if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[0][2] != ' ')
return arr[0][2];
if (1==is_full(arr))/is_full()返回1則return ‘q'
{
return 'q';
}
return 'c';/都不滿足,return ‘c'
}總結(jié)
到此這篇關(guān)于200行C語言代碼實(shí)現(xiàn)簡易三子棋游戲的文章就介紹到這了,更多相關(guān)C語言三子棋游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c語言生成隨機(jī)數(shù)的方法(獲得一組不同的隨機(jī)數(shù))
c語言生成一組不同的隨機(jī)數(shù),大家參考使用吧2013-12-12
適合初學(xué)者的C語言數(shù)據(jù)類型的講解
在 C 語言中,數(shù)據(jù)類型指的是用于聲明不同類型的變量或函數(shù)的一個廣泛的系統(tǒng)。變量的類型決定了變量存儲占用的空間,以及如何解釋存儲的位模式。2022-04-04
C++?Boost?CircularBuffer算法超詳細(xì)精講
Boost是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱。Boost庫是一個可移植、提供源代碼的C++庫,作為標(biāo)準(zhǔn)庫的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開發(fā)引擎之一,是為C++語言標(biāo)準(zhǔn)庫提供擴(kuò)展的一些C++程序庫的總稱2022-11-11

