当前位置: 移动技术网 > 移动技术>移动开发>IOS > 石头剪刀布人工智能代码详解

石头剪刀布人工智能代码详解

2020年07月15日  | 移动技术网移动技术  | 我要评论
石头剪刀布人工智能代码详解#include <iostream>#include <fstream>#include <stdlib.h>#include <time.h>#define MAXN 3using namespace std;struct memPoint{int _list[4];int _all;};这里就没什么好说的了,stdlib与time都是随机数需要的库memPoint _mem[4][4];in

石头剪刀布人工智能代码详解

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <time.h>

#define MAXN 3

using namespace std;

struct memPoint{
	int _list[4];
	int _all;
};

这里就没什么好说的了,stdlib与time都是随机数需要的库

memPoint _mem[4][4];
int _turn=1;
int _win=0;
int _draw=0;
int _lose=0;

_mem是记忆数组,剩下四个整形分别是回合,胜场,平场,负场
_mem[i][m]表示对手出i, 我们出j的状态
_mem[i][m]._all表示这个状态一共经历了几次
_mem[i][m]._list[k]表示这个状态下对手出k出了几次

void GenRand(){
	srand(time(0) );
}

void GenMem(){
	for(int i=0; i<=MAXN; i++){
		for(int m=0; m<=MAXN; m++){
			for(int k=1; k<=MAXN; k++){
				_mem[i][m]._list[k]=1;
			} 
			_mem[i][m]._all=3;
		} 
	}
}

以上是初始化部分,GenRand是随机数撒种,GenMem在上一篇博客也说过
因为模数不能为零,而又要对后面影响不大,所以选择n=3, a1=a2=a3=1

void Debug(int one, int two){
	cout<<"debug"<<endl;/////////////////////
	for(int i=1; i<=MAXN; i++){
		cout<<_mem[one][two]._list[i]<<" ";
	}
	cout<<endl;
}

这个没啥用,是我调试的时候用的

void Explain(){
	cout<<"welcome to challenge my ai. now, you and my ai will choose a number(1~3), and 2>1, 3>2, 1>3. good luck!"<<endl;
}

这个实际上也没啥用,解释一下玩法

void CurParse(int &res){
	cout<<"please input your decision here"<<endl;
	int in;
	cin>>in;
	res=in;
}

输入对手的决策,因为后续可以改输入,还可以汉化
所以我单拎了一个函数,或者说方法

void Decision(int one, int two, int &res){
	//cout<<"AI decision"<<endl;///////////
	int maxNum=_mem[one][two]._all;
	int choose=rand() % maxNum + 1;
	//cout<<"rand="<<choose<<endl;/////////////////
	//Debug(one, two);//////////////////
	int add=0;
	if(choose<=_mem[one][two]._list[1]+add){
		res=2;
		//cout<<"so choose foe may choose 1, us choose 2"<<endl;/////////////// 
		return;
	}
	add+=_mem[one][two]._list[1];
	if(choose<=_mem[one][two]._list[2]+add){
		res=3;
		//cout<<"so choose foe may choose 2, us choose 3"<<endl;/////////////// 
		return;
	}
	res=1;
	//cout<<"so choose foe may choose 3, us choose 1"<<endl;/////////////// 
	return;
}

这里就是重点了,通过(rand mod k) +1来模拟对手的选择
k在1-a1间,我们认为对手会出1,我们就出2
其他类推
因为我们的区间是
1——a1,a1——a1+a2,a1+a2——n
而不是
1——a1,1——a2,1——a3
(这样的话1到底算在哪里?)
所以需要一个add来记录上次排到哪里了
然后因为每个判断后面都有return,所以不用重复判断
即从第一个判断出来后,我们就认为k>a1
同样,从第二个判断出来后,我们就认为k>a1+a2
所以肯定在第三个区间

void WriteOut(int foe, int us){
	cout<<"ai:"<<us<<endl;
	if(foe==1&&us==3){
		cout<<"you win!!!"<<endl;
		_win++;
		return;
	}
	if(foe==3&&us==1){
		cout<<"you lose!!!"<<endl;
		_lose++;
		return;
	}
	if(foe>us){
		cout<<"you win!!!"<<endl;
		_win++;
		return;
	}
	if(foe<us){
		cout<<"you lose!!!"<<endl;
		_lose++;
		return;
	}
	cout<<"draw..."<<endl;
	_draw++;
}

这就没啥好说的了,输出赢还是输还是平

void Game(){
	int lastFoe=0;
	int lastUs=0;
	int curFoe;
	int curUs;
	while(true){
		cout<<"turn:"<<_turn<<" win:"<<_win<<" draw:"<<_draw<<" lose:"<<_lose<<endl;
		Decision(lastFoe, lastUs, curUs);
		CurParse(curFoe);
		WriteOut(curFoe, curUs);
		
		_mem[lastFoe][lastUs]._list[curFoe]++;
		_mem[lastFoe][lastUs]._all++;
		
		lastFoe=curFoe;
		lastUs=curUs;
		
		_turn++;
	}
}

有了上面的决策函数,这里主要就是纪律上次的决策,从记忆数组里取(Decision)
然后刷新后再放回去

int main(){
	cout<<"generating rand decision"<<endl;
	GenRand();
	cout<<"generating first memory"<<endl;
	GenMem();
	cout<<"start!"<<endl;
	Explain();
	Game();
	return 0;
}

主程序就一个一个调就行了

好了,差不多讲完了
如果有 错误/优化/疑问 欢迎提出
WeChat:wxid_ffe28hxx677f32
(其实是我想认识大佬)
——by 于斯为盛

本文地址:https://blog.csdn.net/maxChang_algha/article/details/107297403

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网