目录
一,回合制贪吃蛇
其实贪吃蛇本就是回合制,只是每个回合的时候大概只有0.3秒。
我这里把时间改成不限制,变成真正的回合制。
1,基本功能(代码1)
#include <iostream>
#include <string>
#include <vector>
#include <time.h>
#include <functional>
#include <algorithm>
#include <vector>
#include <queue>
#include <numeric>
#include <map>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <array>
#include <functional>
#include <string.h>
#include <math.h>
#include <fstream>
#include <streambuf>
#include <stdio.h>
#include <mutex>
#include <unordered_map>
#include <iostream>
#include <vector>
#include <iomanip>
#include <string>
#include <algorithm>
#include <cmath>
#include <stack>
#include <set>
#include <queue>
#include <math.h>
#include <functional>
#include <limits>
#include <climits>
#include <stdint.h>
#include <windows.h>
using namespace std;
enum Nod {
Head,
Body,
Apple,
Empty
};
struct AllInfo {
vector<vector<Nod>>m;
int dir = 0;//0上1右2下3左
deque<pair<int, int>>v;//贪吃蛇头即队列头
bool dead = false;
};
int ROW = 10;
int COL = 10;
AllInfo g;
void makeApple()
{
vector<pair<int, int>>s;
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
if (g.m[i][j]== Empty)s.push_back({i,j});
}
}
int id = rand() % s.size();
int r = s[id].first, c = s[id].second;
g.m[r][c] = Apple;
}
void Init()
{
g.m.resize(ROW);
for (auto& v :g.m) {
v.resize(COL);
for (auto& x : v)x = Empty;
}
g.m[0][0] = Head;
g.v.push_back({ 0,0 });
makeApple();
}
void show()
{
system("cls");
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
if (g.m[i][j] == Head)cout << "●";
else if (g.m[i][j] == Body)cout << "○";
else if (g.m[i][j] == Apple)cout << "△";
else if (g.m[i][j] == Empty)cout << "┼";
}
cout << endl;
}
cout << endl << "请输入运动方向,0上1右2下3左4不变方向" << endl;
}
void moved(int d)
{
if (d == 4)d = g.dir;
if (g.dir % 2 != d % 2)g.dir = d;
auto p = g.v.front();
static vector<int> dr = { -1,0,1,0 };
static vector<int> dc = { 0,1,0,-1 };
int r = (p.first + dr[g.dir] + ROW) % ROW;
int c = (p.second + dc[g.dir] + COL) % COL;
if (g.m[r][c] == Body) {
g.dead = true;
return;
}
bool needMakeApple = (g.m[r][c] == Apple);
g.m[p.first][p.second] = Body;
g.m[r][c] = Head;
if (needMakeApple) {
makeApple();
}
else {
p = g.v.back();
g.m[p.first][p.second] = Empty;
g.v.pop_back();
}
g.v.push_front({ r,c });
}
int main()
{
Init();
while (g.v.size() < ROW * COL) {
show();
int d;
cin >> d;
moved(d);
if (g.dead) {
cout << "LOSE!!!";
return 0;
}
if (g.v.size() == ROW * COL) {
cout << "WIN!!!";
return 0;
}
}
return 0;
}
2,运行效果
实心圆是蛇头,空心圆是蛇身,三角形是苹果。
4其实就是跳过输入(有时候贪吃蛇玩家不是主动跳过,是反应不过来)
3,记谱(代码2)
#include <iostream>
#include <string>
#include <vector>
#include <time.h>
#include <functional>
#include <algorithm>
#include <vector>
#include <queue>
#include <numeric>
#include <map>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <array>
#include <functional>
#include <string.h>
#include <math.h>
#include <fstream>
#include <streambuf>
#include <stdio.h>
#include <mutex>
#include <unordered_map>
#include <iostream>
#include <vector>
#include <iomanip>
#include <string>
#include <algorithm>
#include <cmath>
#include <stack>
#include <set>
#include <queue>
#include <math.h>
#include <functional>
#include <limits>
#include <climits>
#include <stdint.h>
#include <windows.h>
using namespace std;
#define LOCAL
/*
#include<opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/core/mat.hpp>
using namespace cv;
#ifdef NDEBUG
#pragma comment(lib,"../x64/vc14/lib/opencv_world452.lib")
#pragma comment(lib,"../x64/vc14/lib/opencv_world452d.lib")
#else
#pragma comment(lib,"../x64/vc14/lib/opencv_world452d.lib")
#pragma comment(lib,"../x64/vc14/lib/opencv_world452.lib")
#endif
*/
//
//int main()
//{
// int s = 0;
// for (int i = 0; i < 10000; i++) {
// s += getMinTime();
// }
// cout << s / 10000;
// return 0;
//}
//auto img = imread("C:/Users/28024/Downloads/组件/7.jfif", 0);
//cv::resize(img, img,Size(918, 918));
//imwrite("C:/Users/28024/Downloads/组件/new7.png",img);
//cout << img.rows;
//freopen("D:/in.txt", "r", stdin);
enum Nod {
Head,
Body,
Apple,
Empty
};
struct AllCurrentInfo {
vector<vector<Nod>>m;
int dir = 0;//0上1右2下3左
deque<pair<int, int>>v;//贪吃蛇头即队列头
bool dead = false;
};
struct HistoryInfo {
unsigned seed;
vector<int>dirs;
};
int ROW = 10;
int COL = 10;
unsigned seed = time(NULL);
AllCurrentInfo g;
HistoryInfo h;
void makeApple()
{
vector<pair<int, int>>s;
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
if (g.m[i][j]== Empty)s.push_back({i,j});
}
}
int id = rand() % s.size();
int r = s[id].first, c = s[id].second;
g.m[r][c] = Apple;
}
void Init()
{
g.m.resize(ROW);
for (auto& v :g.m) {
v.resize(COL);
for (auto& x : v)x = Empty;
}
g.m[0][0] = Head;
g.v.push_back({ 0,0 });
makeApple();
h.seed = seed;
}
void show()
{
system("cls");
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
if (g.m[i][j] == Head)cout << "●";
else if (g.m[i][j] == Body)cout << "○";
else if (g.m[i][j] == Apple)cout << "△";
else if (g.m[i][j] == Empty)cout << "┼";
}
cout << endl;
}
cout << endl << "请输入运动方向,0上1右2下3左,4不变方向, 5显示棋谱" << endl;
}
void moved(int d)
{
h.dirs.push_back(d);
if (d == 4)d = g.dir;
if (g.dir % 2 != d % 2)g.dir = d;
auto p = g.v.front();
static vector<int> dr = { -1,0,1,0 };
static vector<int> dc = { 0,1,0,-1 };
int r = (p.first + dr[g.dir] + ROW) % ROW;
int c = (p.second + dc[g.dir] + COL) % COL;
if (g.m[r][c] == Body) {
g.dead = true;
return;
}
bool needMakeApple = (g.m[r][c] == Apple);
g.m[p.first][p.second] = Body;
g.m[r][c] = Head;
if (needMakeApple) {
makeApple();
}
else {
p = g.v.back();
g.m[p.first][p.second] = Empty;
g.v.pop_back();
}
g.v.push_front({ r,c });
}
int main()
{
Init();
while (g.v.size() < ROW * COL) {
show();
int d;
cin >> d;
if (d == 5) {
cout << h.seed;
for (auto d : h.dirs)cout << " " << d;
Sleep(5000);
} else {
moved(d);
if (g.dead) {
cout << "LOSE!!!";
return 0;
}
if (g.v.size() == ROW * COL) {
cout << "WIN!!!";
return 0;
}
}
}
return 0;
}
4,读谱(代码3)
#include <iostream>
#include <string>
#include <vector>
#include <time.h>
#include <functional>
#include <algorithm>
#include <vector>
#include <queue>
#include <numeric>
#include <map>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <array>
#include <functional>
#include <string.h>
#include <math.h>
#include <fstream>
#include <streambuf>
#include <stdio.h>
#include <mutex>
#include <unordered_map>
#include <iostream>
#include <vector>
#include <iomanip>
#include <string>
#include <algorithm>
#include <cmath>
#include <stack>
#include <set>
#include <queue>
#include <math.h>
#include <functional>
#include <limits>
#include <climits>
#include <stdint.h>
#include <windows.h>
using namespace std;
#define LOCAL
/*
#include<opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/core/mat.hpp>
using namespace cv;
#ifdef NDEBUG
#pragma comment(lib,"../x64/vc14/lib/opencv_world452.lib")
#pragma comment(lib,"../x64/vc14/lib/opencv_world452d.lib")
#else
#pragma comment(lib,"../x64/vc14/lib/opencv_world452d.lib")
#pragma comment(lib,"../x64/vc14/lib/opencv_world452.lib")
#endif
*/
//
//int main()
//{
// int s = 0;
// for (int i = 0; i < 10000; i++) {
// s += getMinTime();
// }
// cout << s / 10000;
// return 0;
//}
//auto img = imread("C:/Users/28024/Downloads/组件/7.jfif", 0);
//cv::resize(img, img,Size(918, 918));
//imwrite("C:/Users/28024/Downloads/组件/new7.png",img);
//cout << img.rows;
//freopen("D:/in.txt", "r", stdin);
enum Nod {
Head,
Body,
Apple,
Empty
};
struct AllCurrentInfo {
vector<vector<Nod>>m;
int dir = 0;//0上1右2下3左
deque<pair<int, int>>v;//贪吃蛇头即队列头
bool dead = false;
};
struct HistoryInfo {
unsigned seed;
vector<int>dirs;
};
int ROW = 10;
int COL = 10;
unsigned seed = time(NULL);
AllCurrentInfo g;
HistoryInfo h;
void makeApple()
{
vector<pair<int, int>>s;
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
if (g.m[i][j]== Empty)s.push_back({i,j});
}
}
if (s.empty())return;
int id = rand() % s.size();
int r = s[id].first, c = s[id].second;
g.m[r][c] = Apple;
}
void Init()
{
srand(seed);
g.m.resize(ROW);
for (auto& v :g.m) {
v.resize(COL);
for (auto& x : v)x = Empty;
}
g.m[0][0] = Head;
g.v.push_back({ 0,0 });
makeApple();
h.seed = seed;
}
void show()
{
system("cls");
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
if (g.m[i][j] == Head)cout << "●";
else if (g.m[i][j] == Body)cout << "○";
else if (g.m[i][j] == Apple)cout << "△";
else if (g.m[i][j] == Empty)cout << "┼";
}
cout << endl;
}
cout << endl << "请输入运动方向,0上1右2下3左,4不变方向, 5显示棋谱" << endl;
}
void moved(int d)
{
h.dirs.push_back(d);
if (d == 4)d = g.dir;
if (g.dir % 2 != d % 2)g.dir = d;
auto p = g.v.front();
static vector<int> dr = { -1,0,1,0 };
static vector<int> dc = { 0,1,0,-1 };
int r = (p.first + dr[g.dir] + ROW) % ROW;
int c = (p.second + dc[g.dir] + COL) % COL;
if (g.m[r][c] == Body) {
g.dead = true;
return;
}
bool needMakeApple = (g.m[r][c] == Apple);
g.m[p.first][p.second] = Body;
g.m[r][c] = Head;
if (needMakeApple) {
makeApple();
}
else {
p = g.v.back();
g.m[p.first][p.second] = Empty;
g.v.pop_back();
}
g.v.push_front({ r,c });
}
int main()
{
cin >> seed;
Init();
while (g.v.size() < ROW * COL) {
show();
int d;
cin >> d;
if (d == 5) {
cout << h.seed;
for (auto d : h.dirs)cout << " " << d;
Sleep(5000);
}
else if (d >= 0 && d <= 4) {
moved(d);
if (g.dead) {
cout << "LOSE!!!";
return 0;
}
if (g.v.size() == ROW * COL) {
cout << "WIN!!!";
return 0;
}
}
}
return 0;
}
5,霸屏
哪个贪吃蛇玩家没有一个霸屏梦?
需要注意的是,及时识别作茧自缚的陷阱。
比如:
还有:
这2个例子都还没有陷入死局,但是如果直奔着苹果去,把苹果吃了就陷入了死局了。
第一次尝试结果:
到这里卡死了
棋谱:
1748794151 2 2 2 1 1 1 1 1 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 1 1 1 2 2 2 2 2 2 2 2 2 3 3 3 0 4 4 4 4 4 4 4 3 3 3 2 2 2 2 2 2 1 1 1 1 1 1 1 0 4 4 4 4 4 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 1 1 1 0 4 4 4 4 4 4 4 4 3 3 2 2 2 2 2 1 1 1 1 1 1 1 2 2 1 1 1 1 1 1 1 0 3 0 0 1 1 0 0 0 3 3 3 3 2 2 2 2 2 2 2 1 1 1 1 0 4 4 3 3 0 4 4 4 4 4 3 3 3 3 0 3 3 0 4 4 4 1 1 1 1 1 1 1 1 1 2 2 2 2 3 0 4 3 3 3 3 3 3 2 2 2 2 2 2 1 1 1 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 1 1 1 1 1 2 2 2 2 3 3 3 3 3 3 0 1 1 1 1 0 3 3 3 3 3 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 0 4 4 4 4 4 4 3 3 3 3 3 3 3 0 1 1 1 1 1 0 3 3 3 3 3 3 2 2 2 2 1 1 1 1 1 2 2 2 2 1 1 0 0 1 1 1 1 1 2 2 1 1 2 3 3 3 3 3 3 2 2 3 3 3 3 3 3 3 3 3 2 1 1 1 1 1 1 1 1 2 3 3 3 2 2 2 2 3 0 4 4 3 2 2 2 2 1 1 1 2 3 3 3 3 0 4 4 4 3 3 3 3 2 2 1 1 1 2 2 2 2 1 1 1 1 1 1 1 1 2 3 3 3 3 3 3 3 3 2 1 1 1 1 1 1 2 2 2 2 3 0 4 4 3 3 3 3 3 3 0 3 3 2 2 1 2 2 2 2 3 3 3 3 3 3 3 3 3 0 0 0 0 1 1 1 1 1 2 3 3 3 3 2 2 1 0 1 2 1 1 1 1 1 0 3 3 0 0 0 1 0 4 4 3 2 2 3 3 3 3 0 0 0 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 2 1 2 2 3 2 2 2 1 1 1 1 1 2 3 3 3 3 3 2 1 1 1 1 1 1 1 1 0 0 0 0 0 0 3 2 2 2 2 2 3 0 0 3 3 3 0 1 1 1 0 3 3 3 3 0 1 1 1 1 0 1 1 1 2 1 0 1 1 1 1 1 0 3 3 3 3 3 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 2 3 3 2 2 2 1 1 1 1 1 1 1 1 0 0 0 0 0 3 2 2 2 2 3 0 3 2 3 0 0 1 1 0 0 0 3 2 2 3 0 0 0 3 2 2 3 0 0 3 2 2 3 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 2 2 3 0 3 3 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 3 2 2 2 2 2 2 2 3 3 3 3 3 3 0 1 1 1 1 1 0 3 3 0 1 1 0 0 0 0 3 2 2 2 3 0 0 0 3 2 2 3 0 0 3 2 2 3 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 1 0 1 1 1 0 0 3 2 3 0 3 3 3 2 2 2 2 2 3 3 3 3 3 3 3 3 0
第二次尝试结果:
手误
第三次尝试结果:
霸屏成功
棋谱:
1748795253 4 4 4 4 4 4 4 3 3 3 3 3 3 3 0 0 0 1 1 1 1 1 1 2 2 2 3 3 3 3 0 0 3 3 3 0 4 4 1 1 1 1 1 0 0 3 3 3 3 3 0 4 4 4 1 1 1 2 2 2 2 3 3 3 3 3 0 0 1 1 1 1 1 0 1 1 0 4 4 3 3 3 2 3 3 2 2 2 2 2 1 1 2 2 1 2 3 3 3 3 0 4 4 4 4 4 4 4 4 1 2 2 2 2 2 2 2 1 1 1 1 1 1 0 0 3 0 0 0 0 0 0 0 1 1 1 2 2 1 1 1 1 1 1 2 3 3 3 3 3 3 3 2 2 3 3 3 3 0 3 3 3 3 3 2 2 2 2 2 2 1 1 1 1 1 1 2 3 3 3 3 3 3 3 0 0 0 0 0 3 3 3 3 3 3 3 3 0 1 1 1 1 1 1 0 0 3 3 3 3 3 3 3 3 3 0 3 3 3 3 3 3 3 3 3 0 3 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 1 2 2 2 2 2 2 1 1 1 1 0 0 0 3 0 0 1 1 1 1 0 0 3 3 3 3 3 3 3 3 0 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 3 0 4 4 4 3 2 2 2 2 3 0 0 0 0 0 0 0 3 3 3 3 3 2 1 1 1 2 2 2 3 0 3 3 3 0 0 0 0 1 1 1 1 1 0 0 0 3 2 3 3 3 3 0 0 0 3 2 2 2 2 2 2 2 2 2 3 3 3 3 0 1 1 0 4 4 4 4 1 0 0 3 3 2 2 2 2 2 3 3 3 3 3 3 2 1 1 1 1 2 3 3 3 3 2 1 1 1 1 2 3 3 3 3 2 1 1 1 1 2 3 3 3 3 2 1 1 1 1 1 0 4 4 4 4 4 1 2 2 2 2 2 2 1 1 1 0 0 0 0 0 0 0 0 0 3 2 2 2 2 2 2 2 2 3 0 0 0 0 0 0 0 0 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 0 0 3 2 2 3 3 3 0 0 0 0 0 0 0 1 1 1 1 1 2 3 3 3 3 2 2 2 2 2 1 0 0 0 0 1 2 2 1 1 2 2 2 2 1 0 0 0 0 0 0 0 0 1 2 2 2 2 2 2 2 2 1 0 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 1 1 1 1 1 0 3 3 3 3 0 4 4 4 4 4 4 1 1 1 1 1 2 3 3 3 3 2 2 2 2 2 1 1 1 1 2 2 1 1 1 0 3 3 0 1 1 0 3 3 3 3 3 3 0 1 1 1 1 1 1 0 3 3 3 3 3 3 0 1 1 1 1 1 1 0 3 3 0 1 1 0 3 3 3 3 3 3 3 3 3 0 4 4 4 4 4 0 4 4 1 1 1 1 1 1 2 3 3 3 3 3 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 0 3 3 3 3 3 3 3 0 1 1 1 1 1 1 1 0 3 3 3 3 3 3 3 0 1 1 1 1 1 1 1 0 3 3 3 3 3 3 3 0 1 1 1 1 1 1 1 0 0 0 3 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 2 3 3 3 3 3 3 3 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 0 3 3 3 3 3 3 3 0 1 1 1 1 1 1 1 0 3 3 3 3 3 3 3 0 1 1 1 1 1 1 1 0 3 3 3 3 3 3 3 0 1 1 1 1 1 1 1 0 0 0 3 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 2 3 3 3 3 3 3 3 2 2 2 2 2
二,霸屏的遗忘算法
针对回合制贪吃蛇,能不能用一个遗忘算法,确保最后能霸屏呢?
1,哈密顿回路
如果ROW*COL是偶数,那很容易构造回路:
如果ROW*COL是奇数,就稍微复杂一点点:
2,基于回路的遗忘算法
只要保持贪吃蛇的蛇头沿着回路运动,最终一定会收尾相接,即霸屏。