我们自己在自己的编译器上创建一个三子棋项目,创建完毕后分别创建test.c,用来测试运行代码,game.h,用来引用所需要的头文件和所需函数的声明,game.c,用来定义game.h中的函数。以后我们写这种代码较长的函数较多的项目,都应该养成分文件的习惯,代码看起来也很分明。
2.在test.c文件中引头文件和写主函数#include"game.h"//因为在game.h中引用头文件,为了方便,我们在test.c和game.c都加上,表示用了game.h里 //面的头文件和game.h里面的函数
void menu()
{
printf("*************************************n");
printf("************ 1.paly **********n");
printf("************ 0.exit **********n");
printf("*************************************n");
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择 >:n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("欢迎下次再玩!n");
break;
default:
printf("输入错误,请重新输入!n");
break;
}
} while (input);
return 0;
}
我们首先需要打印一个菜单让玩家选择,玩家可能玩一次还想再玩一次,所以我们让它至少执行一次,用do while循环,然后循环里面用分支语句来分别跳转玩家的选择。
3.在test.c文件写开始玩游戏代码void game()
{
char board[ROW][COL] = { 0 };//创建一个二维数组棋盘
init_board(board, ROW, COL);//初始化棋盘
display_board(board, ROW, COL);//打印棋盘让玩家看到
}
我们需要将棋盘打印成这种形状:
我们将二维数组棋盘初始化为3行3列的,但是为了让代码灵活起来,我们选择用宏定义,将行定义为ROW,列定义为COL:于是在game.h文件里面:
#define ROW 3 #define COL 34.初始化棋盘
现在game.h文件里面声明初始化棋盘的函数并引用头文件:
#include//初始化棋盘 void init_board(char board[ROW][COL], int row, int col);
接下来转到game.c文件中写函数的定义:
void init_board(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
这里已经将3*3个格子的元素全部初始化为空格。而为什么要初始化为空格不为0,原因是空格占一个字符,0占两个,打印出来会对不齐。
5.打印棋盘在game.h文件里面声明打印棋盘的函数:
//打印棋盘 void display_board(char board[ROW][COL], int row, int col);
接下来转到game.c文件中写函数的定义:
void display_board(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);//要把格子打印在中央
if(j
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("n");
}
}
}
然后我们就成功的打印出了上面图中我们需要的棋盘,当然,也可以把ROW和COL定义的3改为4,就会打印出4*4的棋盘了。
6.开始下棋我们要实现玩家下一步棋,电脑下一步棋,直到有一方赢,所以就是一直循环到有人赢,循环里面,玩家走一步,打印给玩家看,电脑走一步,打印给玩家看,先给死循环,判断条件我们下面再说
void game()
{
char ret = 0;
char board[ROW][COL] = { 0 };
init_board(board, ROW, COL);
display_board(board, ROW, COL);
while (1)
{
player_move(board, ROW, COL);//玩家下棋
display_board(board, ROW, COL);//打印棋盘
computer_move(board, ROW, COL);//电脑下棋
display_board(board, ROW, COL);//打印棋盘
}
}
在game.h中声明玩家下棋和电脑下棋的函数:
//玩家下棋 void player_move(char board[ROW][COL], int row, int col); //电脑下棋 void computer_move(char board[ROW][COL], int row, int col);
在game.c文件中定义这两个函数:
//玩家下棋:
//这里我们把玩家下的子定义为*
void player_move(char board[ROW][COL], int row, int col)
{
printf("玩家下:n");
//判断下棋合法
int x = 0, y = 0;
while (1)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("该坐标已被占用,请重新输入:n");
}
}
else
{
printf("非法坐标,请重新输入:n");
}
}
}
//电脑下棋
//这里我们把电脑下的子定义为#
void computer_move(char board[ROW][COL], int row, int col)
{
printf("电脑下:n");
int x = 0, y = 0;
while (1)
{
x = rand() % row;//产生一个0到2的随机数
y = rand() % col;//产生一个0到2的随机数
//判断坐标合法即可下子
if (x >= 0 && x <= row - 1 && y >= 0 && y <= col - 1 && board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
//这里给电脑下的不需要提示坐标是否合法,玩家的才需要。电脑下了子直接跳出就行了。
}
}
我们在电脑下棋那的x和y要产生随机数,所以我们需要写一个时间种子,在game.h里面引用时间函数的头文件和srand函数的头文件:
#include#include
我们srand函数只需要调用一次,所以我们在main()函数里面调用一次即可:
int main()
{
int input = 0;
srand((unsigned int)time(NULL));//就是这。
do
{
menu();
printf("请选择 >:n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("欢迎下次再玩!n");
break;
default:
printf("输入错误,请重新输入!n");
break;
}
} while (input);
return 0;
}
7.判断谁赢
我们以返回的棋子来判断谁赢或者平局,需要每下一步就判断一次:
我们这里返回*就是玩家赢,返回#就是电脑赢,返回Q就是平局,返回C,就是继续游戏
void game()
{
char ret = 0;
char board[ROW][COL] = { 0 };
init_board(board, ROW, COL);
display_board(board, ROW, COL);
while (1)
{
player_move(board, ROW, COL);
display_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
computer_move(board, ROW, COL);
display_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
{
printf("玩家赢!n");
}
else if (ret == '#')
{
printf("电脑赢!n");
}
else if (ret == 'Q')
{
printf("平局!n");
}
}
在game.h文件中写函数的声明:
//判断谁赢 char is_win(char board[ROW][COL], int row, int col);
在game.c中写函数的定义:
我用了标签flag来判断,使得判断灵活了起来,无论的4*4的还是其它数的,都可以判断
int is_full(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
char is_win(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;//横线判断:
for (i = 0; i < row; i++)
{
int flag1 = 1;
for (j = 0; j < col-1; j++)
{
if (board[i][j] != board[i][j + 1] || board[i][j+1] == ' ')
{
flag1 = 0;
break;
}
}
if (flag1 == 1)
{
return board[i][j];
}
}
//竖直判断:
for (i = 0; i < col; i++)
{
int flag2 = 1;
for (j = 0; j < row - 1; j++)
{
if (board[j][i] != board[j + 1][i]|| board[j+1][i] == ' ')
{
flag2 = 0;
break;
}
}
if (flag2 == 1)
{
return board[j][i];
}
}
//从左到右斜线判断:
int flag3 = 1;
for (i = 0; i < row-1; i++)
{
if (board[i][i] != board[i + 1][i + 1] || board[i+1][i+1] == ' ')
{
flag3 = 0;
break;
}
}
if (flag3 == 1)
{
return board[i][i];
}
//从右到左斜线判断:
int flag4 = 1;
for (i = 0, j = col - 1; i < row, j>0; i++, j--)
{
if (board[i][j] != board[i + 1][j - 1] || board[i+1][j-1] == ' ')
{
flag4 = 0;
break;
}
}
if (flag4 == 1)
{
return board[i][j];
}
int ret = is_full(board, ROW, COL);//判断是否为平局
if (ret == 1)
{
//返回平局
return 'Q';
}
//以上的都不是,就返回继续游戏
return 'C';
}
8.总结
写到这里,恭喜你!你已经把三子棋的代码完成了!
放出最后代码的样子:
test.c文件:
//三子棋
#include "game1.h"
void menu()
{
printf("*************************************n");
printf("************ 1.paly **********n");
printf("************ 0.exit **********n");
printf("*************************************n");
}
void game()
{
char ret = 0;
char board[ROW][COL] = { 0 };
init_board(board, ROW, COL);
display_board(board, ROW, COL);
while (1)
{
player_move(board, ROW, COL);
display_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
computer_move(board, ROW, COL);
display_board(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
{
printf("玩家赢!n");
}
else if (ret == '#')
{
printf("电脑赢!n");
}
else if (ret == 'Q')
{
printf("平局!n");
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择 >:n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("欢迎下次再玩!n");
break;
default:
printf("输入错误,请重新输入!n");
break;
}
} while (input);
return 0;
}
game.h文件:
#pragma once #define ROW 3 #define COL 3 #include#include #include //初始化棋盘 void init_board(char board[ROW][COL], int row, int col); //打印棋盘 void display_board(char board[ROW][COL], int row, int col); //玩家下棋 void player_move(char board[ROW][COL], int row, int col); //电脑下棋 void computer_move(char board[ROW][COL], int row, int col); //判断谁赢 char is_win(char board[ROW][COL], int row, int col);
game.c文件:
#include "game1.h"
//初始化棋盘
void init_board(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void display_board(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if(j
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("n");
}
}
}
void player_move(char board[ROW][COL], int row, int col)
{
printf("玩家下:n");
//判断下棋合法
int x = 0, y = 0;
while (1)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("该坐标已被占用,请重新输入:n");
}
}
else
{
printf("非法坐标,请重新输入:n");
}
}
}
void computer_move(char board[ROW][COL], int row, int col)
{
printf("电脑下:n");
int x = 0, y = 0;
while (1)
{
x = rand() % row;
y = rand() % col;
if (x >= 0 && x <= row - 1 && y >= 0 && y <= col - 1 && board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
int is_full(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
char is_win(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
int flag1 = 1;
for (j = 0; j < col-1; j++)
{
if (board[i][j] != board[i][j + 1] || board[i][j+1] == ' ')
{
flag1 = 0;
break;
}
}
if (flag1 == 1)
{
return board[i][j];
}
}
for (i = 0; i < col; i++)
{
int flag2 = 1;
for (j = 0; j < row - 1; j++)
{
if (board[j][i] != board[j + 1][i]|| board[j+1][i] == ' ')
{
flag2 = 0;
break;
}
}
if (flag2 == 1)
{
return board[j][i];
}
}
int flag3 = 1;
for (i = 0; i < row-1; i++)
{
if (board[i][i] != board[i + 1][i + 1] || board[i+1][i+1] == ' ')
{
flag3 = 0;
break;
}
}
if (flag3 == 1)
{
return board[i][i];
}
int flag4 = 1;
for (i = 0, j = col - 1; i < row, j>0; i++, j--)
{
if (board[i][j] != board[i + 1][j - 1] || board[i+1][j-1] == ' ')
{
flag4 = 0;
break;
}
}
if (flag4 == 1)
{
return board[i][j];
}
int ret = is_full(board, ROW, COL);
if (ret == 1)
{
return 'Q';
}
return 'C';
}
写的不好,欢迎批评指正!你的每一句建议,都对我很重要!希望我们都可以一起进步!



