目录
一 .基本思路
先总览下三子棋实现的整个样板吧
在开始写代码之前,要先对整个代码进行归纳,我们可以将整个代码分为三大部分:第一:用test.c文件来进行游戏的测试逻辑。第二:用game.c文件来进行游戏的实现逻辑。第三:用game.h文件来进行游戏实现函数的声明。在下列正文中,我们将会不断运用到这三个文件
二 .正文
2.1 生成目录
从三子棋的样板可以看出,前面四行是整个游戏的菜单项,会给出player提示1.play或者2.exit选项
如图:
2.1.1 test.c
在test.c文件中,我们需要完成这样的代码从而实现目录的打印
#include"game.h"
void menu()
{
printf("***************************************************\n");
printf("*********** 1.play *************\n");
printf("*********** 0.exit *************\n");
printf("***************************************************\n");
}
void test()
{
int input = 0;
srand((unsigned int)time NULL);
do
{
menu();
printf("请选择");
scanf("%d", &input);
//当用户输入相对应的数字时,我们可以使用switch语句来更好的接收信息
switch (input)
{
case 1:
//当用户输入1时,开始游戏
//game();此时此刻就需要调用game()函数来实现整个游戏的过程,此过程下文会讲到
break;
case 0:
//当用户输入0时,则退出游戏
printf("退出游戏\n");
break;
default:
//当输入其他信息时,则返回错误
printf("选择错误\n");
break;
}
}while (input);//为了使游戏循环出现,我们使用 do while循环语句
}
int main()
{
test();
return 0;
}
可能有人会注意到,第一行并没有之前熟悉的#include<stdio.h>头文件,而是#include"game.h",这里就需要重点说明下,为了使我们的代码块看起来更加清晰,可以将所有的需要定义的头文件函数统一放到game.h文件中,以后需要用到时只需引用下总头文件即可
如图所示:
2.2 初始化棋盘
从这个简易三子棋模板我们可以看出,这里面一共是3*3块格子,想实现这样我们可以通过创建二维数组来实现,即char board[ROW][COL] = { 0 };这里ROW代表行数,COL代表列数。每一块格子里面都是空格,想要实现空格就是我们此步骤的核心目的,即初始化棋盘的每一块格子都是空的,从而方便玩家下棋
2.2.1 test.c
在test.c文件中,我们需要实现这样的代码
#include"game.h"
//引用头文件
void game()
{
//创建二维数组
char board[ROW][COL] = { 0 };
//用InitBoard来初始化二维数组
InitBoard(board,ROW,COL);
}
2.2.2 game.c
在game.c文件中,就需要我们写出初始化棋盘为空格的具体过程了
如图:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
//通过创建变量i,j以及使用循环语句对每一块格子初始化为空格
2.2.3 game.h
在初始化数组之前,需要对InitBoard函数进行声明,需要在game.h文件完成,并且为了后续能够自由的实现多子棋的玩法,并非仅仅是三子棋,则需要在game.h文件中定义行数ROW列数COL的大小,省的以后还需要手动多次修改行数列数
如图:
2.3 打印棋盘
正常的棋盘显示如下图所示:
2.3.1 test.c
在初始化棋盘后,我们需要打印出棋盘来看看初始化后的样子。在test.c文件中就需要完成以下代码:
#include"game.h"
//引用头文件
void game()
{
//创建二维数组
char board[ROW][COL] = { 0 };
//用InitBoard函数来初始化二维数组
InitBoard(board,ROW,COL);
//用DisplayBoard函数来实现对棋盘的打印
DisplayBoard(board, ROW, COL);
}
2.3.2 game.c
如何才能实现棋盘的打印呢,需要思考这样一个问题,在上述棋盘样例中,我们不难发现,棋盘被分成了9块格子,每块格子的分割都有个规律,可将其分为两大类。1:数据行,由 |来实现,可以采用循环语句来打印数据类内容。2:分割行,由---|来实现,也可使用循环语句来打印分割行的内容。
在此文件需要完成的代码:
#include"game.h"
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
}
printf("\n");
}
}
2.3.3 game.h
想要实现game.c对棋盘格式的打印,则现需要在game.h中声明此函数
如图:
2.4 玩家下棋
玩家下棋用‘*’表示
如图所示内容:
2.4.1 test.c
#include"game.h"
void game()
{
//数据存储到一个字符的二维数组中,玩家下棋是‘*’ 电脑下棋是‘#’
char board[ROW][COL] = { 0 };//数组的初始化理想值为空格
InitBoard(board, ROW, COL); //对数组进行初始化函数为空格
DisplayBoard(board, ROW, COL); //打印三子棋模板
while (1) //进行游戏
{
player_move(board, ROW, COL); //玩家先玩
DisplayBoard(board, ROW, COL); //每输入一组数组,相应的三子棋模板也要显示出来
}
2.4.2 game.c
实现玩家下棋这个函数的整个过程,则需要完成下列代码:
#include"ghame.h"
//玩家下棋
void player_move(char board[ROW][COL], int row, int col)
{
printf("玩家下棋:>");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
while (1)
{
if (x > 0 && x <= row && y > 0 & y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("该位置已被占用,请重新输入\n");
break;
}
}
else
{
printf("非法输入,请重新输入\n");
break;
}
}
}
2.4.3 game.h
在定义函数player_move之前,需要在game.h中声明此函数。
如图:
2.5 电脑下棋
当玩家下完棋时,电脑下,原理与玩家差不多。
实现后如图所示:
2.5.1 test.c
想实现上图所示的内容,需要在test.c中写出下列代码
void game()
{
//数据存储到一个字符的二维数组中,玩家下棋是‘*’ 电脑下棋是‘#’
char board[ROW][COL] = { 0 };//数组的初始化理想值为空格
InitBoard(board, ROW, COL); //对数组进行初始化函数为空格
DisplayBoard(board, ROW, COL); //打印三子棋模板
while (1) //进行游戏
{
player_move(board, ROW, COL); //玩家先玩
DisplayBoard(board, ROW, COL); //每输入一组数组,相应的三子棋模板也要显示出来
computer_move(board, ROW, COL); //电脑再玩
DisplayBoard(board, ROW, COL);
}
2.5.2 game.c
与玩家下棋方式不同的是,由于玩家下棋是凭借主观臆断,而电脑则需要随机下一个位置,就需要我们用到srand((unsigned int)time NULL);从而确保电脑下的是个随机值
则在game.c需要完成这样的代码:
//电脑下棋用‘#’
void computer_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
在test.c需要完成这样的代码
void test()
{
int input = 0;
srand((unsigned int)time NULL); //确保电脑下的位置是个随机数
}
2.5.3 game.h
相应的定义头文件也是少不了的:
2.6 判断局面
当玩家和电脑下到一定程度时,则需要判断胜负或平局
如图:
判断输赢的字符:
//玩家赢 - '*'
//电脑赢 - '#'
//平均 --- 'Q'
//继续 --- 'C'
2.6.1 test.c
char ret = 0; //全局变量定义ret
void game()
{
//数据存储到一个字符的二维数组中,玩家下棋是‘*’ 电脑下棋是‘#’
char board[ROW][COL] = { 0 };//数组的初始化理想值为空格
InitBoard(board, ROW, COL); //对数组进行初始化函数为空格
DisplayBoard(board, ROW, COL); //打印三子棋模板
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");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
}
2.6.2 game.c
int is_full(char board[ROW][COL], int row, int col)
{
int i = 0;
int 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;
//判断胜利条件---三行
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
//判断胜利条件---三列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[1][i];
}
}
//判断胜利条件---对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
{
return board[0][0];
}
if (board[2][0] == board[1][1] & board[1][1] == board[0][2] && board[2][0] != ' ')
{
return board[2][0];
}
//判断平局
if (is_full(board, row, col) == 1)
{
return 'Q';
}
//继续
else
return 'C';
}
2.6.3 game.h
三 .游戏整个代码
3.1 test.c 文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("***************************************************\n");
printf("*********** 1.play *************\n");
printf("*********** 0.exit *************\n");
printf("***************************************************\n");
}
int ret = 0;
void game()
{
char board[ROW][COL] = { 0 };
InitBoard(board,ROW,COL);
DisplayBoard(board, ROW, COL);
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");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
}
void test()
{
int input = 0;
srand((unsigned int)time NULL);
do
{
menu();
printf("请选择");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误\n");
break;
}
}while (input);
}
int main()
{
test();
return 0;
}
3.2 game.c 文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
if (i < row - 1)
{
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("玩家下棋:>");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
while (1)
{
if (x > 0 && x <= row && y > 0 & y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("该位置已被占用,请重新输入\n");
break;
}
}
else
{
printf("非法输入,请重新输入\n");
break;
}
}
}
void computer_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
int is_full(char board[ROW][COL], int row, int col)
{
int i = 0;
int 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;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[1][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
{
return board[0][0];
}
if (board[2][0] == board[1][1] & board[1][1] == board[0][2] && board[2][0] != ' ')
{
return board[2][0];
}
if (is_full(board, row, col) == 1)
{
return 'Q';
}
else
return 'C';
}
3.3 game.h 文件
#pragma once
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL], int row, int col);
void DisplayBoard(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);