综合练习——三子棋小游戏

前言

相信大家在小时候都与自己的同桌在上课时一起摸过鱼,三子棋小游戏可以说是最方便的摸鱼小游戏了,那时的我们是在纸上玩,现在我们想在电脑上玩,我们可以不可以自己设计一下呢?下面我就与大家分享一下三子棋小游戏的设计思路,以及代码实现。

思路分析

首先我们想要下棋,是不是必须有个棋盘供我们落子,小时候我们用方格信纸画一个3x3的区域当棋盘,我们可以把这个区域看作一个二维数组,再设计上一些边界装饰,我们的棋盘就有了。那这个小游戏都需要什么功能呢?首先游戏需要有一个开始菜单,进入游戏会显示主菜单。其次我们在电脑上下棋肯定是与电脑对弈,所以我们还需要有玩家下棋,电脑下棋两个功能,我们需要知道玩家和电脑在哪里下棋了,我们是不是需要打印棋盘,最后还要判断是玩家获胜还是电脑获胜还是平局,是不是还需要一个判断胜负的功能。好了有了以上的功能我们就可以实现三子棋小游戏的全部需求。那这些功能具体如何实现,下面我带领大家一起来在编译器中写一写。

代码实现

游戏框架和主界面功能

void menu()
{
	printf("************************\n");
	printf("************************\n");
	printf("*******1.开始游戏*******\n");
	printf("*******0.结束游戏*******\n");
	printf("************************\n");
	printf("************************\n");
}

void game()
{
	//二维数组当作棋盘
	char board[ROW][COL] = { 0 };

}

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");
		  }
		}
	} while (input);
}

在这里插入图片描述

因为我们想让游戏游戏可以反复游玩,所以我们使用循环来实现,进入循环首先打印游戏主菜单,我们对游戏菜单使用了函数封装,调用函数就可以实现打印主菜单,之后由玩家进行选择是否开始游戏,通过分支进行选择开始游戏或者结束游戏,玩家选择开始游戏后进入游戏的主体游玩,游戏主体我们同样使用函数封装起来。游戏的框架结构就是这样,之后我们就需要对游戏主体进行设计。

游戏主体

打印棋盘

我们想要打印棋盘的样子如下图

在这里插入图片描述
我们想打印这样一个三子棋的棋盘,首先我们对棋盘进行分析,可以将棋盘拆分,我们将第一行看作 数据 | 数据 | 数据这样子,第二行我们看作---|---|---,我们可以将这两行的输出看成一组,作为一行进行打印,这样就可以对应我们的二维数组的行数,我们就可以把打印的这些东西放入一个循环当中for (i = 0; i < row; i++)根据数组的行数进行打印。

void dispaly_board(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("|");
		}

		printf("\n");

		for (j = 0; j < col; j++)
			{
				printf("---");
				printf("|");
			}

		printf("\n");

	}
}

在这里插入图片描述
好像这样还是与我们预期的样子不一样,我们继续分析,将我们需要的三子棋棋盘与这个棋盘对比,我们发现我们需要的棋盘,最后一个数据右边不打印|,最下面一组数据不打印---|---|---所以我们需要对打印进行一定约束,加上一定的限制条件,让他实现我们想要的需求。

void dispaly_board(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");

	}
}

我们让---|---|---少打印一次,同时数组元素后边的|也少打印一次,我们加上这些限制条件这样就可以实现我们的需求了。当我们执行代码
在这里插入图片描述
我们发现好像还是与我们的需求不一样啊,这怎么对不齐呢?原因是我们的二维数组进行初始化时,元素都为\0,我们需要对二维数组进行初始化,将数组元素都初始为' '

初始化二维数组

我们对二维数组进行初始化,编写一个初始化函数

void init_board(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 player_move(char board[ROW][COL], int row, int col)
{
	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("您选择的位置已有旗子,请重新选择:");
			}
		}

		else
		{
			printf("您输入的坐标不合理,请重新选择:");
		}
	}
}

如上图,玩家进行输入,之后进行判断,如果在棋盘范围之内,再次判断,如果为空那么就落子,我们设计玩家的棋子为*,落子后跳出循环,如果已有旗子那么给出提示,再次让玩家输入,如果玩家输入旗子坐标超出棋盘,也给出相应提示,再次让玩家输入。
在这里插入图片描述
效果如上图,这里解释一下为什么board[x-1][y-1]这里的坐标要减一,因为玩家不懂编程,所以他们不知道数组的元素下标是从0开始的,所以他们输入的坐标值会比数组元素下标大1,所以这里进行了减一处理。

电脑下棋

电脑下棋思路同玩家下棋,只是电脑不需要提示,如果判断错误直接继续循环就可以了。那电脑如何获得坐标呢?我们可以使用随机数来获取,具体代码如下

void computer_move(char board[ROW][COL], int row, int col)
{

	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

因为我们使用了随机值,所以在主函数中要设置随机值的生成器srand((unsigned)time(NULL));还需要引入头文件#include<stdlib.h> #include<time.h>,我们将生成的随机值跟他对应的行和列取余数,这样就控制了随机的大小,使生成的数就在棋盘的坐标范围内,之后进入循环,进行判断如果为' '就落子,我们设计的电脑玩家的棋子为#

在这里插入图片描述

判断输赢

既然使游戏必然有输赢,所以我们需要设计一个函数来判断输赢

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][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 (1 == is_full(board,ROW,COL))
	{
		return 'Q';
	}
	else
	{
		return 'C';
	}
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当我们的同一行或者同一列再或者对角线上的数组元素相等且不等于' '时,我们返回对应的符号

if (ret == '*')
	{
		printf("恭喜你,你赢了!!\n");
	}
	else if (ret == '#')
	{
		printf("对不起,电脑赢了!!\n");
	}
	else if (ret == 'Q')
	{
		printf("平局,在来一局吧!!\n");
	}

通过判断给出相应的信息,最后可以打印一下棋盘最后的结果。

最终游戏代码展示

test.c

#define  _CRT_SECURE_NO_WARNINGS 1

#include"game1.h"

void menu()
{
	printf("************************\n");
	printf("************************\n");
	printf("*******1.开始游戏*******\n");
	printf("*******0.结束游戏*******\n");
	printf("************************\n");
	printf("************************\n");
}

void game()
{
	//二维数组当作棋盘
	char board[ROW][COL] = {0};
	char ret = 0;
	初始化
	init_board(board,ROW,COL);
	//打印棋盘
	dispaly_board(board, ROW, COL);

	while (1)
	{
		//玩家下棋
		player_move(board, ROW, COL);
		//查看是否落子
		dispaly_board(board, ROW, COL);
		//判断输赢
		ret = is_win(board, ROW, COL);
		if (ret != 'C')
			break;
		//电脑下棋
		computer_move(board, ROW, COL);
		//查看是否落子
		dispaly_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");
	}

	dispaly_board(board, ROW, COL);
}

int main()
{
	srand((unsigned)time(NULL));
	int input = 0;

	do
	{
		menu();
	
		printf("请选择是否开始游戏:");
		scanf("%d", &input);

		switch (input)
		{
		case 1:
		   {
			game();
			break;
		   }
		case 0:
		  {
			printf("游戏结束\n");
			break;
		  }

		default :
		  {
			printf("您的选择有误,请重新选择\n");
		  }
		}
	} while (input);
}

game.c

#define  _CRT_SECURE_NO_WARNINGS 1

#include"game1.h"

//初始化棋盘
void init_board(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 dispaly_board(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)
{
	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("您选择的位置已有旗子,请重新选择:");
			}
		}

		else
		{
			printf("您输入的坐标不合理,请重新选择:");
		}
	}
}

void computer_move(char board[ROW][COL], int row, int col)
{

	while (1)
	{
		int x = rand() % row;
		int 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][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 (1 == is_full(board,ROW,COL))
	{
		return 'Q';
	}
	else
	{
		return 'C';
	}
}

game.h

#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define ROW 3
#define COL 3

//初始化数组
void init_board(char board[ROW][COL], int row, int col);

//打印数组
void dispaly_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);
  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
### 回答1: 好的,我可以用C语言编写一个三子棋小游戏。首先,我们需要定义一个3x3的数组,用于储存游戏状态。然后,我们需要定义一个函数来检查游戏是否已经结束,并且确定谁是获胜者。最后,我们需要定义一个函数来接受玩家的输入,并在棋盘上进行更新。 ### 回答2: 三子棋是一款简单易学的棋类游戏,通常在3x3的棋盘上进行。游戏的目标是让自己先下的一方在横、竖、斜线上收集到三个棋子。 如果要用C语言编写一个简单的三子棋小游戏,可以按照以下步骤: 1. 创建一个3x3的棋盘。可以使用一个二维数组来表示,初始化为一个空棋盘。 2. 创建一个函数来打印当前的棋盘状态。使用for循环遍历数组,根据不同的元素值输出相应的棋子或空位。 3. 创建一个函数来接收玩家输入。可以使用scanf函数获取玩家输入的行数和列数,并进行合法性检查。 4. 创建一个函数来判断游戏是否结束。在每一步玩家下子之后,判断棋盘上是否有三个连成一线的棋子,如果有则游戏结束。 5. 创建一个函数来进行游戏的主循环。在每一轮循环中,先打印当前棋盘的状态,再接受玩家输入,判断是否游戏结束,然后轮到另一方下子。 6. 在主函数中调用游戏的主循环函数,开始游戏。 以上是一个简单的实现思路,具体的代码结构和函数实现可以根据个人的理解和编程能力进行调整和优化。希望这个回答能够对您有所帮助! ### 回答3: 三子棋是一种双人策略棋盘游戏,其中玩家轮流将自己的棋子放在一个3x3的格子上,第一个放满一条线的玩家即获胜。下面是使用C语言编写的一个简单的三子棋小游戏: ```c #include <stdio.h> char board[3][3]; // 3x3棋盘 void init_board() { for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { board[i][j] = ' '; // 棋盘初始化为空格 } } } void print_board() { printf(" 1 2 3\n"); for(int i = 0; i < 3; i++) { printf("%d ", i+1); for(int j = 0; j < 3; j++) { printf("%c ", board[i][j]); } printf("\n"); } } int check_winner() { for(int i = 0; i < 3; i++) { if(board[i][0] != ' ' && board[i][0] == board[i][1] && board[i][0] == board[i][2]) { return 1; // 行相同 } if(board[0][i] != ' ' && board[0][i] == board[1][i] && board[0][i] == board[2][i]) { return 1; // 列相同 } } if(board[0][0] != ' ' && board[0][0] == board[1][1] && board[0][0] == board[2][2]) { return 1; // 对角线相同 } if(board[0][2] != ' ' && board[0][2] == board[1][1] && board[0][2] == board[2][0]) { return 1; // 对角线相同 } return 0; // 无人获胜 } int main() { int row, col, currentPlayer = 1, moves = 0; init_board(); // 初始化棋盘 while(1) { printf("Player %d, enter row and column: ", currentPlayer); scanf("%d%d", &row, &col); if(row > 3 || col > 3 || row < 1 || col < 1 || board[row-1][col-1] != ' ') { printf("Invalid move!\n"); continue; // 无效棋步 } // 根据当前玩家确定棋子类型 char player = (currentPlayer == 1) ? 'X' : 'O'; board[row-1][col-1] = player; print_board(); if(check_winner()) { printf("Player %d wins!\n", currentPlayer); break; // 有人获胜,游戏结束 } if(moves == 8) { printf("It's a draw!\n"); break; // 平局,游戏结束 } // 轮换玩家 currentPlayer = (currentPlayer == 1) ? 2 : 1; moves++; } return 0; } ``` 运行上述代码后,玩家1用`X`表示,玩家2用`O`表示。每位玩家依次输入所选择的行和列,然后程序判断棋步的合法性并更新棋盘。当有玩家连成一条线或所有格子放满时,游戏结束并宣布获胜方或平局结果。 这只是一个简单的三子棋小游戏,仅供学习和娱乐使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悲伤猪小猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值