三子棋介绍:
简单的小游戏。在3×3的棋盘中下棋,一方的棋子连成一条直线(横竖斜)则获胜。用初步学习到的C语言知识去实现它,来锻炼自己。
基本思路:
分三个文件test.c game.h game.c
分别完成主函数和菜单;游戏相关函数的声明和头文件的引用;实现游戏相关函数
1.选择菜单
2.初始化棋盘
3.显示棋盘
4.下棋
5.判断输赢
1.选择菜单
int main()
{
int input = 0;
do
{
menu();
printf("请输入>:");
scanf("%d", &input);
switch (input)
{
case 1:game();
break;
case 0:printf("退出游戏\n");
break;
default:printf("选择错误,请重新选择\n");
break;
}
} while (input);//判断看的是input只有输入0(0为假,非零为真)才会退出
return 0;
}
这里选择使用do while循环,会先执行一次循环体的内容即选择菜单之后在去判断循环条件;判断的条件是输入的数字。
菜单函数
//菜单
void menu()
{
printf("****** 1.paly ******\n");
printf("****** 0.exit ******\n");
printf("****************************\n");
printf("****************************\n");
}
2.初始化棋盘
菜单完成了,当玩家选择1之后要玩游戏就需要有棋盘。
1.棋盘用字符构成;创建字符类型的二维数组。行和列的英文为Rows and Columns,简称ROW和COL
char board[COL][ROW];
我们把游戏相关的内容都放在一个新开的.h文件中当我们要使用的时候只要引用就ok啦。
这里要注意用自己的头文件要用英文的双引号括起来。这样分开放好处就是画面整洁有调理,出问题检查起来也会方便些,在game.h文件中定义了ROW和COL,如果想使用其他规格的棋盘也只要在头文件中修改就好了。
接着初始化棋盘,把初始化棋盘的函数声明放在game.h中具体函数放在game.c中
void init(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;用i表示行,j表示列,利用循环把数组中每一个元素的改为字符空格(刚开始时数组内容应该全部为空格);
棋盘到这打印出来啥也看不到,为了看到的棋盘更美观,在格子之间加上横竖分割开
3.显示棋盘
void display(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");//换行
}
}
展示一下使用row和col代替数字作为行和列的好处;在game.h文件中把row和col修改成十
4.玩家移动
使用‘x’表示玩家的棋子。
逻辑:
1.玩家下棋输入坐标,但是注意数组下标是从0开始的。横纵坐标范围1-3,在数组中是0-2;
2.输入的坐标不能被占用才能下棋。
3.输入坐标不能超过范围。
在game.h中声明,在game.c文件中完成。
void player(char board[ROW][COL], int row, int col)//玩家下棋
{
int x = 0;
int y = 0;
printf("玩家下棋");
while (1)
{
printf("请输入坐标:>\n");
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");
}
}
}
5.电脑随机下棋
1.电脑下棋用'#'表示;
2.电脑随机落子,落子有范围,落子坐标不能被占用。
为实现随机使用rand()函数,要包含头文件#include <stdlib.h>,在使用rand函数之前要生成随机的种子,就要用到srand函数,要在主函数中使用srand((unsigned int)time(NULL))
使用时间戳生成随机的参数用到time函数头文件为<time.h>
- 注意事项:需要注意的是,由于
rand()
生成的数字是伪随机数,因此它们是可预测的,只要你知道种子值和参数。此外,一些语言和库提供了更好的随机数生成器,例如更长的周期、更低的噪音等。
注意:x = rand() % row; y = rand() % col;应该在循环中实现否则可能会卡在这一步,没办法break;
void computer(char board[ROW][COL], int row, int col)//电脑随机下棋
{
printf("电脑下棋\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;//限制x的范围在0-2
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
6.判断输赢
玩家赢返回 '*'
//电脑赢返回 '#'
//平局返回 'Q'
//游戏继续返回 'C'
1.判断赢棋:三个相同的连成一列/行/对角线;
2.判断是否平局,创建一个新的函数判断,如果数组中没有' '了则满棋了。
static int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i <= row; i++)
{
int j = 0;
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 < row; i++)//三个相同的连成一行
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0];//直接返回棋子,因为三个是一样的,玩家是*电脑是#。
}
}
for (i = 0; i < col; i++)//三个相同的连成一列
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
}
//三个相同的连成对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//判断是否平局
if (IsFull(board, row, col))//新创建一个函数来判断是否棋盘上放满了棋子,函数返回1或0;
{
return 'Q';
}
return 'C';
}
static int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i <= row; i++)
{
int j = 0;
for (j = 0; j <= col; j++)
{
if(board[i][j])
return 0;
}
}
return 1;
}
代码实现:
game.h文件:
#pragma once
#include<stdio.h>
#include<time.h>
#include <stdlib.h>
#define ROW 3
#define COL 3
void init(char board[ROW][COL], int row, int col);//初始化棋盘
void display(char board[ROW][COL], int row, int col);//显示棋盘
void player(char board[ROW][COL], int row, int col);//玩家下棋
void computer(char board[ROW][COL], int row, int col);//电脑下棋
char iswin(char board[ROW][COL], int row, int col);//判断输赢
game.c文件:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void init(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 display(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]);
// }
// printf("\n");//打印完一行换行
// }
//}
void display(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(char board[ROW][COL], int row, int col)//玩家下棋
{
int x = 0;
int y = 0;
printf("玩家下棋");
while (1)
{
printf("请输入坐标:>\n");
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(char board[ROW][COL], int row, int col)//电脑随机下棋
{
printf("电脑下棋\n");
int x = 0;
int y = 0;
x = rand() % row;//限制x的范围在0-2
y = rand() % col;
while (1)
{
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//玩家赢返回 '*'
//电脑赢返回 '#'
//平局返回 'Q'
//游戏继续返回 'C'
static int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i <= row; i++)
{
int j = 0;
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 < row; i++)//三个相同的连成一行
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0];//直接返回棋子,因为三个是一样的,玩家是*电脑是#。
}
}
for (i = 0; i < col; i++)//三个相同的连成一列
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
}
//三个相同的连成对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//判断是否平局
if(IsFull(board,row,col))//新创建一个函数来判断是否棋盘上放满了棋子,函数返回1或0;
{
return 'Q';
}
return 'C';
}
test.c文件:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//菜单
void menu()
{
printf("****** 1.paly ******\n");
printf("****** 0.exit ******\n");
printf("****************************\n");
printf("****************************\n");
}
void game()
{ char ret = 0;
char board[COL][ROW];
//下棋肯定要有棋盘啊整个棋盘先
init(board, COL, ROW);
display(board, COL, ROW);
while(1)
{
player(board, COL, ROW);//玩家下
display(board, COL, ROW);
//判断输赢
ret = iswin(board, COL, ROW);
if (ret != 'C')//判断是否结束
{
break;
}
computer(board, COL, ROW);//电脑下
display(board, COL, ROW);
ret = iswin(board, COL, ROW);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
}
int main()
{
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);//判断看的是input只有输入0(0为假,非零为真)才会退出
return 0;
}