想必三字棋大家都玩过吧!
如图所示,大家一下子就明白了。
那么如何通过代码实现这个小游戏呢?
来,跟着我一步步操作。
当你想写一个程序,首先我们要分析他的流程:
以上是大体的三子棋流程,头脑里有一个大概,接下来我们开始写代码。
首先我们打印开始界面:
void menu()
{
printf("*************************\n");
printf("***** 1. play ******\n");
printf("***** 0. exit ******\n");
printf("*************************\n");
}
接下来写主程序:
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);
return 0;
}
void game()
{
char board[ROW][COL];
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
}
首先创建一个text.c文件,我们定义一个数组char board[ROW][COL]
用于存放我们下棋的棋子,这里选择使用#define
定义ROW为行数,COL为列数,方便更改棋盘尺寸。然后定义初始化函数InitBoard
和打印函数DisplayBoard
,同时我们再创建一个game.c文件存放创建的自定义函数。
void InitBoard(char board[ROW][COL], int row, int col)
{
int i;
for (i = 0; i < row; i++) {
int j;
for (j = 0; j < col; j++) {
board[i][j] = ' ';
}
}
}
在棋盘每个位置放置空格表示没有棋子。
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i;
int j;
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");
}
printf("\n");
}
运用for语句嵌套打印出我们想要的棋盘形状。
将以上两个函数存放到text.c的game函数中,同时我开始构建玩家下棋的代码。
void game()
{
char board[ROW][COL];
char ret = 0;
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
while (1) {
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
}
}
}
这里我们定义了玩家下棋函数PlayerMove
和电脑下棋函数ComputerMove
,每次下完棋我们需要看到棋下在哪了,所以每次下棋之后都需要调用DisplayBoard
函数打印到屏幕。
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x, y;
while (1) {
printf("请输入要下棋的坐标:");
scanf("%d %d", &x, &y);
if (x >= 0 && x <= row && y >= 0 && y <= col) {
if (board[x - 1][y - 1] == ' ') {
board[x-1][y-1] = '*';
break;
}
else {
printf("该坐标被占用,请输入其他坐标\n");
}
}
else {
printf("该坐标非法,请重新输入。\n");
}
}
}
首先输入想下棋的坐标x ,y
,然后判断当x,y
满足在棋盘内坐标合法。
当坐标合法时判断下棋前该坐标为空格,则在该坐标下棋。
如果该坐标已经有棋了,则打印"该坐标被占用,请输入其他坐标"
进行提示。
下完棋通过break
结束运行。
注意!!!
玩家下棋时输入的坐标跟数组定义的坐标不一样,所以判断玩家的坐标时需要将坐标减一进行判断。
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;
}
}
}
这里调用rand函数生成随机数,通过% row % col
限制随机数范围不得超过棋盘大小。用if
语句判断在没人下棋的地方下棋(即空格处),下完棋通过break
结束运行。
记得在主函数添加srand((unsigned int)time(NULL));
srand设置随机数生成器,调用time函数作为种子,time函数返回值为time_z,所以通过unsigned int强制类型转换。rand和srand存放于#include
。
我们将以上两个下棋函数放到game函数内
void game()
{
char board[ROW][COL];
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
while (1) {
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
}
}
static int IsFull(char board[ROW][COL], int row, int col)
{
int i, j;
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)
{
for (int 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 (int 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))
return 'Q';
return 'C';
}
我们定义IsWin
判断输赢和IsFull
判断平局。
三个棋连成一条直线则赢,所以利用坐标进行判断。
如果每个格子都有棋,但不能判断输赢,则为平局。
我们定义ret变量接收IsFull
函数返回值判断输赢
玩家赢 - ’ * ',电脑赢 - ’ # ',平局 — ’ Q ‘,游戏继续-’ C ’
void game()
{
char board[ROW][COL];
char ret = 0;
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
while (1) {
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C') {
break;
}
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C') {
break;
}
}
if (ret == '*') {
printf("玩家赢了\n");
}
else if (ret == '#')
{
printf("电脑赢了\n");
}
else
{
printf("平局\n");
}
}
每次玩家和电脑下完棋,都需要分别进行判断输赢。
我们可以创建一个game.h头文件包含我们所用的库函数和自定义函数。
每次通过#include "game.h"
调用。
#include
#define ROW 3
#define COL 3
#include
#include
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 col);
char IsWin(char board[ROW][COL]);
text.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("*************************\n");
printf("***** 1. play ******\n");
printf("***** 0. exit ******\n");
printf("*************************\n");
}
void game()
{
char board[ROW][COL];
char ret = 0;
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
while (1) {
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C') {
break;
}
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
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);
return 0;
}
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void InitBoard(char board[ROW][COL], int row, int col)
{
int i;
for (i = 0; i < row; i++) {
int j;
for (j = 0; j < col; j++) {
board[i][j] = ' ';
}
}
}
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i;
int j;
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");
}
printf("\n");
}
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x, y;
while (1) {
printf("请输入要下棋的坐标:");
scanf("%d %d", &x, &y);
if (x >= 0 && x <= row && y >= 0 && 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;
}
}
}
static int IsFull(char board[ROW][COL], int row, int col)
{
int i, j;
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)
{
for (int 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 (int 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))
return 'Q';
return 'C';
}
game.h
#pragma once
#include
#define ROW 3
#define COL 3
#include
#include
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 col);
char IsWin(char board[ROW][COL]);