手把手教你实现简单三子棋

三子棋


我们分以下三个文件来实现三子棋:

test.c - 主函数 - 设计整个游戏过程

游戏的逻辑

game.c - 函数的实现

game.h - 函数的声明

成品展示

image-20210424162314511

首先我们打印一个菜单,让玩家选择,选择后会出现棋盘界面,然后让玩家输入坐标下棋。

image-20210424162512894

然后玩家输入坐标,之后实现玩家走和电脑走,直到一方获得胜利,游戏结束。

image-20210424162925946

首先讲一讲我们整体的思路框架,我们设计这个游戏,让玩家想玩的时候可以一直玩,所以我们采用do…while循环语句,然后打印菜单,写一个菜单函数,让玩家进行选择,这里我们采用switch分支语句,当我们选择1时进入游戏,此时需要写一个游戏函数,选择0时退出游戏,选择其他时,告诉他选择错误,重新输入,我们发现当选择1和选择错误时我们需要循环继续,退出游戏是我们退出循环的时候,所以我们将while()里的循环条件设置成玩家输入的选择。

我们的整体逻辑框架如下代码:

test.c

void game()
{
	//游戏的实现,这里先不写  
}
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 2:
                printf("退出游戏\n");
                break;
        default:
                printf("选择错误,重新选择\n");
                break;
        }
    }while(input)
    return 0;
}

那么游戏的实现,我们该怎么弄呢?

从刚开始我们进行成品展示时,实现这个游戏,我们需要:

1、创建一个存储数据的字符数组

行列的元素个数我们用#define在game.h中定义常量,这样我们需要修改棋盘行列时就很简单,使我们的游戏程序更加灵活多变。

char board[ROW][COL] = { 0 };

2、初始化数据

首先打印的界面数据为空的,我们需要初始化数据为空格

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]=' ';
        }
    }
}

3、打印棋盘

image-20210424171050102

打印棋盘代码:

void DisplayBoard(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++)
        {
            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");
        }
    }
}

image-20210425210310094

我们把打印棋盘分成了打印数据行和打印分割行,我们发现分割行我们只打印两次,最后一行我们不需要分割行,所以我们将判断条件设置为i<row-1时我们才打印分割行,我们再看列,最后一行我们不打印|,所以|的打印我们给判断条件j<col-1。

我们还有另一种打印棋盘的方法:

//打印棋盘
//写法不好,当我们想要打印10*10的棋盘时,行会打印10行,但列是3列,通用性不好
//void DisplayBoard(char board[ROW][COL],int row,int col)
//{
//    int i=0;
//    for(i=0;i<row;i++)
//    {
//        printf(" %c | %c | %c \n",board[i][0],board[i][1],board[i][2]);
//        if(i<row-1)
//        {
//            printf("---|---|---\n");
//        }
//    }
//}

但是这种不太建议,写法不好,这个代码只操作了行,不操作列,当我们想要打印10*10的棋盘时,行会打印10行,但列是3列,通用性不好。

4、玩家走

玩家走的函数代码如下:

void PlayerMove(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 <= 3)
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("该坐标已被占用,请重新选择坐标\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入\n");
		}
	}
}

首先我们需要判断该玩家输入的下棋坐标是否合法,我们的棋盘是三行三列,所以玩家输入的坐标需要再范围内,如果坐标合法了,我们再判断该坐标是否被占用,如果没有被占用,则将该坐标所对应数组下标数据赋值为‘*’(因为我们玩家玩游戏时输入(1,1)坐标时,对应的数组下标为board[0] [0],所以我们判断条件的数组下标需要设置为x-1,y-1)。

5、判断输赢

首先我们看一下判断输赢的基本框架:

我们设定判断输赢函数的返回值

1.玩家赢,返回*
2.电脑赢,返回#
3.平局,返回Q
4.游戏继续,返回C

ret = IsWin(board, ROW, COL);
//1.玩家赢,返回*
//2.电脑赢,返回#
//3.平局,返回Q
//4.游戏继续,返回C

我们在玩家走后判断输赢,在循环内部判断,如果返回的不是C,则说明游戏结束,则跳出循环判断其他三种情况

if (ret != 'C')//游戏已结束
{
    break;
}

循环外面判断:

	if (ret == '*')
	{
		printf("玩家赢\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢\n");
	}
	else if (ret == 'Q')
	{
		printf("平局\n");
	}

判断输赢函数代码:

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[2][2] != ' ')
	{
		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)
	{
		return 'Q';
	}
	return 'C';

}

我们需要判断行、列、对角线是否形成三个一样的字符,以及棋盘是否满判断游戏是否结束,因为我们假定1.玩家赢,返回*,2.电脑赢,返回#所以我们判断行列对角线时可以直接return三个里面任意一个字符,平局我们需要写一个棋盘是否满的函数,如果返回值为1,则表示满–平局,如果电脑赢,玩家赢,平局这三个都不满足,则游戏继续,return字符‘C’。
判断棋盘是否满的代码

//判断棋盘是否满
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;
}

访问数组每个元素,如果有一个元素等于字符空格,则不满,返回0。

6、电脑走

电脑走函数代码:

void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑走\n");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

电脑走我们可以弄个随机数,x给他取余行,y取余列,x范围就为0到row-1,y范围就为0到col-1,所以我们直接将下标设置为x,y进行判断是否为空格字符,我们设置一个循环,当坐标被占用时,则一直循环。

7、再次判断输赢

由成品展示,我们需要实现以上功能,我们需要在玩家走后要判断输赢,在电脑走后判断输赢。

test.c中的游戏函数代码如下:

void game()
{
	//1.创建存储数据的字符数组,行列的元素我们用#define定义,这样我们需要修改棋盘行列时就很简单
	char board[ROW][COL] = { 0 };
	//2.首先打印的界面数据为空的,我们需要初始化数据为空格
	InitBoard(board, ROW, COL);
	//3.打印棋盘
	DispalyBoard(board, ROW, COL);
	char ret = 0;
	while (1)
	{
		//4.玩家走
		PlayerMove(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		//1.玩家赢,返回*
		//2.电脑赢,返回#
		//3.平局,返回Q
		//4.游戏继续,返回C
		DispalyBoard(board, ROW, COL);
		if (ret != 'C')//游戏已结束
		{
			break;
		}
		
		//电脑走
		ComputerMove(board, ROW, COL);
		ret = IsWin(board, ROW, COL);
		DispalyBoard(board, ROW, COL);
		if (ret != 'C')//游戏已结束
		{
			break;
		}
		
	}
	if (ret == '*')
	{
		printf("玩家赢\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢\n");
	}
	else if (ret == 'Q')
	{
		printf("平局\n");
	}
	
}

游戏的实现中用到的函数我们在game.h文件中声明

game.h

#pragma once
#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 DispalyBoard(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], int row, int col);

我们在game.c中写函数的定义

game.c

#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]=' ';
        }
    }
}
//打印棋盘
//写法不好,当我们想要打印10*10的棋盘时,行会打印10行,但列是3列,通用性不好
//void DisplayBoard(char board[ROW][COL],int row,int col)
//{
//    int i=0;
//    for(i=0;i<row;i++)
//    {
//        printf(" %c | %c | %c \n",board[i][0],board[i][1],board[i][2]);
//        if(i<row-1)
//        {
//            printf("---|---|---\n");
//        }
//    }
//}

//打印棋盘函数定义
void DisplayBoard(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++)
        {
            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 PlayerMove(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 <= 3)
		{
			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)
{
	printf("电脑走\n");
	while (1)
	{
		int x = rand() % row;
		int 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 < 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[2][2] != ' ')
	{
		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)
	{
		return 'Q';
	}
	return 'C';

}

test.c

#include"game.h"
void game()
{
	//1.创建存储数据的字符数组,行列的元素我们用#define定义,这样我们需要修改棋盘行列时就很简单
	char board[ROW][COL] = { 0 };
	//2.首先打印的界面数据为空的,我们需要初始化数据为空格
	InitBoard(board, ROW, COL);
	//3.打印棋盘
	DispalyBoard(board, ROW, COL);
	char ret = 0;
	while (1)
	{
		//4.玩家走
		PlayerMove(board, ROW, COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		//1.玩家赢,返回*
		//2.电脑赢,返回#
		//3.平局,返回Q
		//4.游戏继续,返回C
		DispalyBoard(board, ROW, COL);
		if (ret != 'C')//游戏已结束
		{
			break;
		}
		
		//电脑走
		ComputerMove(board, ROW, COL);
		ret = IsWin(board, ROW, COL);
		DispalyBoard(board, ROW, COL);
		if (ret != 'C')//游戏已结束
		{
			break;
		}
		
	}
	if (ret == '*')
	{
		printf("玩家赢\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢\n");
	}
	else if (ret == 'Q')
	{
		printf("平局\n");
	}
	
}
void menu()
{
	printf("**************************\n");
	printf("***********1.play*********\n");
	printf("***********0.exit*********\n");
	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;
}

如有疑问,请留言!欢迎大家学习交流!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
PyTorch是一个用于深度学习的开源Python库,它提供了丰富的工具和函数,可以简化神经网络模型的实现。Transformers是一种用于自然语言处理的深度学习模型,其基本方法是通过自注意力机制来实现文本序列的编码和解码。下面将手把手你如何使用PyTorch实现Transformers。 1. 首先,安装PyTorch库。可以通过pip命令来安装:`pip install torch`。 2. 导入必要的库。在代码的开头,导入PyTorch和Transformers相关的库: ``` import torch from transformers import BertModel, BertTokenizer ``` 3. 加载预训练的Transformers模型和分词器。Transformers库提供了一些预训练的模型,可以从Hugging Face的模型库中下载。我们使用Bert模型作为例子: ``` model_name = 'bert-base-uncased' model = BertModel.from_pretrained(model_name) tokenizer = BertTokenizer.from_pretrained(model_name) ``` 4. 输入编码。将文本输入编码成模型所需的格式。使用分词器对文本进行分词,并将分词后的结果转化为模型所需的编码格式: ``` text = "I love PyTorch" tokens = tokenizer.tokenize(text) input_ids = tokenizer.convert_tokens_to_ids(tokens) input_tensor = torch.tensor([input_ids]) ``` 5. 模型前向计算。将输入数据传入模型进行前向计算: ``` model_output = model(input_tensor) ``` 6. 获取特征表示。从模型输出中获取特征表示。对于Bert模型,可以获取词嵌入和每个词的隐藏状态: ``` embeddings = model_output[0] # 词嵌入 hidden_states = model_output[2] # 每个词的隐藏状态 ``` 7. 解码输出。根据任务需求,对模型的输出进行解码。例如,可以使用BertPooler层获取整个句子的语义表示: ``` pooler_output = model.pooler(hidden_states[-1]) # BertPooler层 ``` 以上就是用PyTorch实现Transformers的基本步骤。根据具体任务的不同,可以对模型进行进一步的调整和优化。希望这个手把手程能够帮到你!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小赵小赵福星高照~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值