1、分模块的写法
首先,我先介绍一下分模块的写法。我们一般分为三个模块
头文件:game.h 这里包含着对函数的声明
源文件:game.c 这里包含着对函数的实现
源文件:test.c 这里就是调用函数的部分也就是主函数在的地方(记得包含文件)
2、三字棋的思路
首先,我们要明白在写这种比较长的程序时一定要从主函数开始顺着往下写
1、既然是游戏那我们必然得先有一个菜单,此时就有了menu函数
2、有了菜单,玩家就会输入,这样接受了输入后,就要对他不同的输入值做出不同的反应。这样就用switch函数来进行分流。因为需要进行区分继续玩还是直接退出于是在switch外有套了一层循环。
3、选择了0,直接退出。选了1,那么进行游戏调用game()函数,来进行游戏。
3、源代码
下面为你们展示原代码:如需要可以自己复制使用(但是记得分文件)
game.h
#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.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 Playermove(char Board[Row][Col], int row, int col);
//电脑下棋
void ComputerMove(char Board[Row][Col], int row, int rol);
//判断输赢
char Iswin(char Board[Row][Col],int row,int col);
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char Board[Row][Col], int row, int col)//初始化
{
int j = 0;
for (j = 0; j < row; j++)
{
int i = 0;
for (i = 0; i < col; i++)
{
Board[j][i] = ' ';
}
}
}
void DisplayBoard(char Board[Row][Col], int row, int col)
{
int j = 0;
for (j = 0; j < row; j++)
{
int i = 0;
for (i = 0; i < col; i++)
{
printf(" %c ", Board[j][i]);
if (i < col - 1)
{
printf("|");
}
}
printf("\n");
for (i = 0; i < col; i++)
{
if (j < row - 1)
{
printf("---");
}
if (i < col - 1 && j < row - 1)
{
printf("|");
}
}
printf("\n");
}
}
void Playermove(char Board[Row][Col], int row, int col)
{
int i = 0;
int j = 0;
int x = 0;
int y = 0;
while (1)
{
printf("请输入要下棋的坐标(用空格隔开):>");
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 ComputerMove(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 Isfull(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 Iswin(char Board[Row][Col], int row, int col)
{
//赢
//玩家赢返回'*'
//电脑赢返回'#'
//行
int i = 0;
for (i = 0; i < col; i++)
{
if (Board[i][0] == Board[i][1] && Board[i][2] == Board[i][0] && Board[i][0] != ' ')
{
return Board[i][0];
}
}
//列
for (i = 0; i < row; i++)
{
if (Board[0][i] == Board[1][i] && Board[0][i] == Board[2][i] && Board[0][i] != ' ')
{
return Board[0][i];
}
}
//平局返回'C'
if (Isfull( Board,row,col)==1)
{
return 'C';
}
//继续返回'Q'
return 'Q';
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("**************************\n");
printf("**************************\n");
printf("*******1.play*************\n");
printf("*******2.exit*************\n");
printf("**************************\n");
printf("**************************\n");
}
void game()
{
char Board[Row][Col] = { '0' };
//初始化棋盘
InitBoard(Board, Row, Col);
//打印棋盘
DisplayBoard(Board, Row, Col);
char ret = 0;
while (1)
{
//玩家下棋
Playermove(Board, Row, Col);
DisplayBoard(Board, Row, Col);
ret=Iswin(Board, Row, Col);
printf("%c", ret);
if (ret != 'Q')
{
break;
}
//电脑下棋
ComputerMove(Board, Row, Col);
DisplayBoard(Board, Row, Col);
ret=Iswin(Board, Row, Col);
if (ret != 'Q')
{
break;
}
}
if (ret == '*')
{
printf("玩家胜利\n");
}
else if (ret == '#')
{
printf("电脑胜利\n");
}
else if (ret == 'C')
{
printf("平局\n");
}
}
int main()
{
int input = 0;
do
{
srand((unsigned int)time(NULL));
menu();
printf("请输入:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("游戏结束");
break;
default:
printf("输入错误,请重新输入:>");
break;
}
} while (input);
}
4、算法
4.1.初始化棋盘
下面为你们分析一下各个函数的算法,也game()函数的思路
一开始先初始化,将数组中的内容全部清空
void InitBoard(char Board[Row][Col], int row, int col)//初始化
{
int j = 0;
for (j = 0; j < row; j++)
{
int i = 0;
for (i = 0; i < col; i++)
{
Board[j][i] = ' ';
}
}
}
4.2打印棋盘
然后既然要下棋,那必须先将棋盘打印出来
需要较好的人机交互性,那我们必须将棋盘的打印变得细分化,可以在ROW,COI改变是也会跟着改变。
于是就有了这种打印方式。先打印 空格+数组元素+空格;在打印竖线;再打印横线。
void DisplayBoard(char Board[Row][Col], int row, int col)
{
int j = 0;
for (j = 0; j < row; j++)
{
int i = 0;
for (i = 0; i < col; i++)
{
printf(" %c ", Board[j][i]);
if (i < col - 1)
{
printf("|");
}
}
printf("\n");
for (i = 0; i < col; i++)
{
if (j < row - 1)
{
printf("---");
}
if (i < col - 1 && j < row - 1)
{
printf("|");
}
}
printf("\n");
}
}
4.3玩家下棋
然后就是玩家下棋
注意:坐标对不对,坐标是不是空的
void Playermove(char Board[Row][Col], int row, int col)
{
int i = 0;
int j = 0;
int x = 0;
int y = 0;
while (1)
{
printf("请输入要下棋的坐标(用空格隔开):>");
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");
}
}
}
4.4电脑下棋
接着就是电脑下棋
同样也是
注意:坐标对不对,坐标是不是空的
void ComputerMove(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;
}
}
}
4.5判断输赢
最后也就是看输赢
这里我用的是自己利用循环来逐一判断
根据不同的结果返回不同的值来给主函数进行判断
char Iswin(char Board[Row][Col], int row, int col)
{
//赢
//玩家赢返回'*'
//电脑赢返回'#'
//行
int i = 0;
for (i = 0; i < col; i++)
{
if (Board[i][0] == Board[i][1] && Board[i][2] == Board[i][0] && Board[i][0] != ' ')
{
return Board[i][0];
}
}
//列
for (i = 0; i < row; i++)
{
if (Board[0][i] == Board[1][i] && Board[0][i] == Board[2][i] && Board[0][i] != ' ')
{
return Board[0][i];
}
}
//平局返回'C'
if (Isfull( Board,row,col)==1)
{
return 'C';
}
//继续返回'Q'
return 'Q';
}