vs2008 error C2440: “static_cast”: ……

本文详细介绍了在使用Visual Studio 2008开发C++项目时遇到的错误C2440问题,即关于消息映射的类型转换错误。通过调整消息函数的返回类型、修改消息映射参数以及确保消息处理函数正确处理参数,可以解决这一问题。提供了解决方案并解释了背后的原因。

vs2008 error C2440: “static_cast”: 无法从“void (__thiscall CMainFrame::* )(void)”转换为“LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)”解决办法  

头文件MainFrm.h: 
#define UM_PROGRESS WM_USER+1 //定义消息 
afx_msg void OnProgress(); // 生成的消息映射函数 
源文件MainFrm.cpp: 
//消息映射 
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) 
ON_MESSAGE(UM_PROGRESS,&CMainFrame::OnProgress) 
END_MESSAGE_MAP() 
//消息实现 
void CMainFrame::OnProgress() 
{ 
//todo: 
} 

VS2008对消息的检查更为严格,以前在VC6下完全正常运行的消息映射在VS2008下编译不通过

ON_MESSAGE(WM_message,OnMyMessage);
OnMessage返回值必须为LRESULT,其形式为:afx_msg LRESULT OnMessage(WPARAM, LPARAM);如果不符合,则有错误提示:
error C2440: “static_cast”: 无法从“void (__thiscall CMainFrame::* )(void)”转换为“LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)”

解决方法如下:

首先,把原来的消息函数返回值类型改为LRESULT,函数内可以随便写个 return 0; 然后消息函数的参数必须改写成(WPARAM wParam,LPARAM lParam)而不论这两个参数是否用得到;最后,消息映射如ON_MESSAGE(UM_PROGRESS,&CMainFrame::OnProgress)

先给出完整代码,请给出完整的2个函数,要求注释仅解释功能,不添加任何类似于添加了……、修改了……的注释: #pragma once #define NOMINMAX #include <iostream> #include <vector> #include <queue> #include <map> #include <string> #include <cstdio> #include <cctype> #include <cmath> #include <algorithm> #include <filesystem> #include <fstream> #include <random> #include <stdexcept> #include <windows.h> #include <climits> using PII = std::pair<int, int>; using str = std::string; int role_count, snack_count; void clear() { std::system("cls"); } void wait(double second) { Sleep(static_cast<DWORD>(second * 1000)); } void wait_key() { std::system("pause"); } int ran(int l, int r) { static std::random_device rd; static std::mt19937 gen(rd()); std::uniform_int_distribution dis(l, r); return dis(gen); } str get_key(double time) { HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); DWORD prevMode; GetConsoleMode(hInput, &prevMode); SetConsoleMode(hInput, ENABLE_WINDOW_INPUT | ENABLE_PROCESSED_INPUT); DWORD startTime = GetTickCount64(); while (true) { DWORD elapsed = GetTickCount64() - startTime; if (elapsed >= static_cast<DWORD>(time)) { SetConsoleMode(hInput, prevMode); return "\0"; } DWORD available; if (!GetNumberOfConsoleInputEvents(hInput, &available) || available == 0) { wait(0.01); continue; } INPUT_RECORD inputRecord; DWORD numEventsRead; if (ReadConsoleInput(hInput, &inputRecord, 1, &numEventsRead)) { if (inputRecord.EventType == KEY_EVENT && inputRecord.Event.KeyEvent.bKeyDown) { WORD vkCode = inputRecord.Event.KeyEvent.wVirtualKeyCode; if (vkCode == VK_ESCAPE) { SetConsoleMode(hInput, prevMode); return "ESC"; } if (vkCode == VK_UP) { SetConsoleMode(hInput, prevMode); return "↑"; } if (vkCode == VK_DOWN) { SetConsoleMode(hInput, prevMode); return "↓"; } if (vkCode == VK_LEFT) { SetConsoleMode(hInput, prevMode); return "←"; } if (vkCode == VK_RIGHT) { SetConsoleMode(hInput, prevMode); return "→"; } if (vkCode == VK_RETURN) { SetConsoleMode(hInput, prevMode); return "ENTER"; } CHAR asciiChar = inputRecord.Event.KeyEvent.uChar.AsciiChar; if (asciiChar > 0 && !std::iscntrl(asciiChar)) { SetConsoleMode(hInput, prevMode); return str(1, asciiChar); } } } } } class ColorStr { private: str outputStr; WORD textColor; WORD originalAttr; WORD ParseColor(const str& colorStr) const { if (colorStr.empty()) return 0x07; try { size_t pos = 0; int value = std::stoi(colorStr, &pos, 16); if (pos == colorStr.size()) { return static_cast<WORD>(value & 0xFF); } } catch (...) {} return 0x07; } public: ColorStr() : textColor(0x07), originalAttr(0x07) { outputStr = " "; } void SetStr(const str& b) { outputStr = b; } str GetStr() const { return outputStr; } void SetColor(const str& a) { textColor = ParseColor(a); } void print() { HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csbi; if (GetConsoleScreenBufferInfo(hConsole, &csbi)) { originalAttr = csbi.wAttributes; } else { originalAttr = 0x07; } SetConsoleTextAttribute(hConsole, textColor); std::cout << outputStr; SetConsoleTextAttribute(hConsole, originalAttr); std::cout.flush(); } }; template <typename Describe, typename Value> class data_list { using Descr = Describe; using pdv = std::pair<Descr, Value>; std::map<Descr, Value> data; public: data_list() {} ~data_list() {} void add(Descr des, Value val) { data.insert({ des, val }); } void erase(Descr des) { data.erase(des); } void print() { for (auto i : data) { std::cout << i.first << ' ' << i.second << std::endl; } } size_t size() { return data.size(); } void print(Descr idx) { if (data.empty()) return; std::cout << idx << ':' << data[idx] << std::endl; } Value& operator[](Descr idx) { return data[idx]; } operator std::vector<pdv>() { std::vector<pdv> temp; for (const auto& p : data) { temp.push_back(p); } return temp; } auto begin() { return data.begin(); } auto end() { return data.end(); } }; class screen { using vcc = std::vector<std::vector<ColorStr >>; vcc scr; size_t n, m; data_list<str, int> data; public: screen(size_t n_, size_t m_) : n(n_), m(m_) { vcc temp(n, std::vector<ColorStr>(m)); for (auto& row : temp) { for (auto& cell : row) { cell.SetStr(" "); cell.SetColor("F0"); } } scr = temp; } int& Data(str des) { return data[des]; } void add(str des, int val) { data.add(des, val); } void erase(str des) { data.erase(des); } void print() { ColorStr border; border.SetColor("F1"); border.SetStr("+"); border.print(); for (size_t i = 0; i < m; i++) { border.SetStr("-"); border.print(); } border.SetStr("+\n"); border.print(); for (auto& row : scr) { border.SetStr("|"); border.print(); for (auto& cell : row) { cell.print(); } border.SetStr("|\n"); border.print(); } border.SetStr("+"); border.print(); for (size_t i = 0; i < m; i++) { border.SetStr("-"); border.print(); } border.SetStr("+\n"); border.print(); data.print(); } std::vector<ColorStr>& operator[](int idx) { return scr[idx]; } auto begin() { return scr.data(); } auto end() { return scr.data() + n; } size_t x_size() { return n; } size_t y_size() { return m; } }; class role { public: role(screen& screen_) : scr(screen_) { role_count++; } virtual ~role() { role_count--; } virtual void operator=(const role& oth) { scr = oth.scr; } protected: screen& scr; }; class apple : public role { int x_, y_; public: apple(screen& screen_) : role(screen_) { regenerate(); } void regenerate() { int sx = scr.x_size(), sy = scr.y_size(); do { x_ = ran(0, sx - 1); y_ = ran(0, sy - 1); } while (scr[x_][y_].GetStr() != " "); } void update() { scr[x_][y_].SetStr("c"); scr[x_][y_].SetColor("F4"); } int x() { return x_; } int y() { return y_; } }; class snack : public role { std::queue<PII> sna; apple& app; int dirx, diry; str name, current_dir; bool died, IsRobot; str color_code; void calculate_safe_direction(int x, int y) { int sx = scr.x_size(); int sy = scr.y_size(); std::vector<int> distances = { y, sy - 1 - y, x, sx - 1 - x }; int max_index = std::max_element(distances.begin(), distances.end()) - distances.begin(); switch (max_index) { case 0: dirx = 0; diry = -1; current_dir = "←"; break; case 1: dirx = 0; diry = 1; current_dir = "→"; break; case 2: dirx = -1; diry = 0; current_dir = "↑"; break; case 3: dirx = 1; diry = 0; current_dir = "↓"; break; } } int dis(int ax, int ay, int bx, int by) { return std::abs(ax - bx) + std::abs(ay - by); } public: explicit snack(screen& screen_, apple& apple_, str name_, int x, int y, bool IsPlayer = false) : role(screen_), app(apple_), name(name_), died(false), IsRobot(!IsPlayer) { dirx = diry = 0; int sx = scr.x_size(), sy = scr.y_size(); if (x < 0) throw std::out_of_range("x<0"); if (y < 0) throw std::out_of_range("y<0"); if (x >= sx) throw std::out_of_range("x>=screen_x"); if (y >= sy) throw std::out_of_range("y>=screen_y"); if (name_ == "Robot_A") { color_code = "F3"; } else if (name_ == "Robot_B"){ color_code = "F5"; } else { color_code = "F2"; } sna.push({ x, y }); scr[x][y].SetStr(current_dir); scr[x][y].SetColor(color_code); scr.add(name_, 0); snack_count++; calculate_safe_direction(x, y); } ~snack() { scr.erase(name); } void die() { size_t sz = sna.size(); for (size_t i = 0; i < sz; i++) { PII f = sna.front(); sna.pop(); scr[f.first][f.second].SetColor("F8"); sna.push(f); } snack_count--; died = true; throw std::runtime_error(name + "死了\n总长度达到:" + std::to_string(scr.Data(name) + 1) + '\n'); } void ChangeDir(str new_dir) { if (new_dir == "↑" && (dirx != 1 || IsRobot)) { dirx = -1; diry = 0; current_dir = "↑"; } else if (new_dir == "↓" && (dirx != -1 || IsRobot)) { dirx = 1; diry = 0; current_dir = "↓"; } else if (new_dir == "←" && (diry != 1 || IsRobot)) { dirx = 0; diry = -1; current_dir = "←"; } else if (new_dir == "→" && (diry != -1 || IsRobot)) { dirx = 0; diry = 1; current_dir = "→"; } else if (new_dir != "" && !IsRobot) throw std::invalid_argument("错误的方向参数:" + new_dir); } void UpDate(bool Auto = true) { if (died) return; if (IsRobot && Auto) { std::vector<std::tuple<str, int, int >> directions = { {"↑", -1, 0}, {"↓", 1, 0}, {"←", 0, -1}, {"→", 0, 1} }; str opposite_dir; if (current_dir == "↑") opposite_dir = "↓"; else if (current_dir == "↓") opposite_dir = "↑"; else if (current_dir == "←") opposite_dir = "→"; else opposite_dir = "←"; auto& head = sna.back(); int ax = app.x(), ay = app.y(); int best_dist = INT_MAX; str best_dir = current_dir; bool found_safe_move = false; for (const auto& [dir, dx, dy] : directions) { if (dir == opposite_dir) continue; int nx = head.first + dx; int ny = head.second + dy; if (nx < 0 || ny < 0 || nx >= static_cast<int>(scr.x_size()) || ny >= static_cast<int>(scr.y_size())) continue; if (scr[nx][ny].GetStr() != " " && scr[nx][ny].GetStr() != "c") continue; int dist = dis(ax, ay, nx, ny); if (dist < best_dist || (dist == best_dist && dir == current_dir)) { best_dist = dist; best_dir = dir; found_safe_move = true; } else if (found_safe_move == false) { best_dir = dir; found_safe_move = true; } } if (found_safe_move) { ChangeDir(best_dir); } } auto head = sna.back(); scr[head.first][head.second].SetStr(current_dir); int nx = head.first + dirx; int ny = head.second + diry; if (nx < 0 || ny < 0 || nx >= static_cast<int>(scr.x_size()) || ny >= static_cast<int>(scr.y_size())) die(); if (scr[nx][ny].GetStr() != " " && scr[nx][ny].GetStr() != "c") die(); if (scr[nx][ny].GetStr() == "c") { app.regenerate(); scr.Data(name)++; } else { PII tail = sna.front(); sna.pop(); scr[tail.first][tail.second].SetStr(" "); scr[tail.first][tail.second].SetColor("F0"); } sna.push({ nx, ny }); scr[nx][ny].SetStr(current_dir); scr[nx][ny].SetColor(color_code); } }; str filename = "snack.data"; data_list<str, int> score_list; void run_snack() { clear(); str name; std::printf("请输入蛇的名字:"); std::cin >> name; screen scr(20, 20); apple app(scr); int x, y; std::map<int, bool> IsX, IsY; x = ran(0, 19), y = ran(0, 19); bool isquit = name == "ooseven"; snack PlayerSnack(scr, app, name, x, y, !isquit); IsX[x] = true, IsY[y] = true; x = ran(0, 19); while (!IsX[x]) x = ran(0, 19); y = ran(0, 19); while (!IsY[y]) y = ran(0, 19); snack RobotSnackA(scr, app, "Robot_A", x, y, false); IsX[x] = true, IsY[y] = true; x = ran(0, 19); while (!IsX[x]) x = ran(0, 19); y = ran(0, 19); while (!IsY[y]) y = ran(0, 19); snack RobotSnackB(scr, app, "Robot_B", x, y, false); IsX[x] = true, IsY[y] = true; wait_key(); clear(); if (isquit) { bool IsDisplay; str IsT; printf("是否显示过程(T/t)?输入其他则不显示:"); std::cin >> IsT; IsDisplay = IsT == "T" || IsT == "t"; while (true) { try { clear(); std::string key = get_key(100); if (key == "ESC") { scr.print(); std::printf("\n游戏暂停中(按回车键继续,ESC键退出本局游戏)……\n"); std::fflush(stdout); str key = get_key(10); while (key != "ENTER" && key != "ESC") { wait(0.01); key = get_key(10); } clear(); if (key == "ESC") { throw std::runtime_error(name + "中途退出了\n总长度达到:" + std::to_string(scr.Data(name) + 1) + '\n'); } } if (key == "\0") { if (IsDisplay) { for (int i = 0; i < 9; i++) { PlayerSnack.UpDate(); app.update(); scr.print(); wait(0.2); clear(); } PlayerSnack.UpDate(); } else { for (int i = 0; i < 10; i++) { PlayerSnack.UpDate(); app.update(); } } } else { PlayerSnack.ChangeDir(key); PlayerSnack.UpDate(false); } RobotSnackA.UpDate(); RobotSnackB.UpDate(); app.update(); scr.print(); wait(0.2); } catch (const std::exception& e) { str temp = e.what(); bool equal = true; for (int i = 0; i < static_cast<int>(name.size()); i++) { if (temp[i] != name[i]) { equal = false; break; } } if (equal) { score_list[name] = std::max(score_list[name], scr.Data(name)); std::printf("游戏结束:\n%s\n", temp.c_str()); std::printf("当前最高分:%d\n", score_list[name]); std::printf("----------------积分列表-----------------\n"); std::printf("玩家\t\t最高分\n"); using psi = std::pair<str, int>; std::vector<psi> temp_list = score_list; std::stable_sort(temp_list.begin(), temp_list.end(), [](const psi& a, const psi& b) { return a.second > b.second; }); for (auto& i : temp_list) { std::printf("%-20s\t\t%d\n", i.first.c_str(), i.second); } std::cout << "-----------------------------------------" << std::endl; wait_key(); break; } } } } else { while (true) { try { clear(); std::string key = get_key(100); if (key == "ESC") { scr.print(); std::printf("\n游戏暂停中(按回车键继续,ESC键退出本局游戏)……\n"); std::fflush(stdout); str key = get_key(10); while (key != "ENTER" && key != "ESC") { wait(0.01); key = get_key(10); } clear(); if (key == "ESC") { throw std::runtime_error(name + "中途退出了\n总长度达到:" + std::to_string(scr.Data(name) + 1) + '\n'); } } PlayerSnack.ChangeDir(key); PlayerSnack.UpDate(); RobotSnackA.UpDate(); RobotSnackB.UpDate(); app.update(); scr.print(); wait(0.2); } catch (const std::exception& e) { str temp = e.what(); bool equal = true; for (int i = 0; i < static_cast<int>(name.size()); i++) { if (temp[i] != name[i]) { equal = false; break; } } if (equal) { score_list[name] = std::max(score_list[name], scr.Data(name)); std::printf("游戏结束:\n%s\n", temp.c_str()); std::printf("当前最高分:%d\n", score_list[name]); std::printf("----------------积分列表-----------------\n"); std::printf("玩家\t\t最高分\n"); using psi = std::pair<str, int>; std::vector<psi> temp_list = score_list; std::stable_sort(temp_list.begin(), temp_list.end(), [](const psi& a, const psi& b) { return a.second > b.second; }); for (auto& i : temp_list) { std::printf("%-20s\t\t%d\n", i.first.c_str(), i.second); } std::cout << "-----------------------------------------" << std::endl; wait_key(); break; } } } } } void start() { clear(); score_list = data_list<str, int>(); if (!std::filesystem::exists(filename)) { std::printf("未找到存档文件 %s\n", filename.c_str()); wait(0.5); clear(); return; } std::ifstream fin(filename); if (!fin.is_open()) { std::printf("打开文件失败\n"); wait(0.5); clear(); return; } std::string header; std::getline(fin, header); if (header != "~") { std::printf("无效文件格式! 期望'~',实际'%s'\n", header.c_str()); fin.close(); wait(0.5); clear(); return; } int seed, salt, res; fin >> seed >> salt >> res; fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); int calculated = (seed * 997 + salt) % 10000; if (calculated != res) { std::printf("存档校验失败! 计算值:%d 文件值:%d\n", calculated, res); fin.close(); wait(0.5); clear(); return; } int record_count; fin >> record_count; fin.ignore(); for (int i = 0; i < record_count; ++i) { std::string name; int score; std::getline(fin, name); fin >> score; fin.ignore(); score -= salt; if (fin.fail()||score%seed) { std::cerr << "读取分数失败,记录索引: " << i << std::endl; break; } score_list.add(name, score); } fin.close(); std::printf("成功读取 %d 条记录\n", record_count); wait_key(); clear(); } void end() { clear(); std::ofstream fout(filename); if (!fout.is_open()) { std::printf("创建文件失败\n"); wait(0.5); clear(); return; } fout << "~\n"; int seed = ran(1, 256); int salt = ran(1000, 9999); int res = (seed * 997 + salt) % 10000; fout << seed << ' ' << salt << ' ' << res << std::endl; fout << score_list.size() << std::endl; for (auto& i : score_list) { str temp = i.first; for (auto& c : temp) { } fout << temp << '\n' << i.second * seed + salt << std::endl; } fout.flush(); fout.close(); std::printf("成功保存 %lld 条记录\n",score_list.size()); wait_key(); clear(); } void launch_snack() { start(); char go = 'T'; while (go == 'T' || go == 't') { clear(); run_snack(); std::printf("再来一次(T/t)? 输入其他则退出:"); std::cin >> go; } end(); return; }
最新发布
10-20
将这段代码的std::string全部改为str以及其他可以用using缩写的,由于代码过长,只需给出修改的部分: #pragma once #define NOMINMAX #include #include #include #include #include #include #include #include #include #include #include #include #include #include <windows.h> #include using PII = std::pair<int, int>; using ll = long long; using dou = double; using ld = long double; using str = std::string; int role_count, snack_count; void clear() { std::system(“cls”); } void wait(dou second) { Sleep(static_cast(second * 1000)); } void wait_key() { std::system(“pause”); } int ran(int l, int r) { static std::random_device rd; static std::mt19937 gen(rd()); std::uniform_int_distribution dis(l, r); return dis(gen); } str get_key(double time) { HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); DWORD prevMode; GetConsoleMode(hInput, &prevMode); SetConsoleMode(hInput, ENABLE_WINDOW_INPUT | ENABLE_PROCESSED_INPUT); DWORD startTime = GetTickCount64(); while (true) { DWORD elapsed = GetTickCount64() - startTime; if (elapsed >= static_cast<DWORD>(time)) { SetConsoleMode(hInput, prevMode); return "\0"; } DWORD available; if (!GetNumberOfConsoleInputEvents(hInput, &available) || available == 0) { wait(0.01); continue; } INPUT_RECORD inputRecord; DWORD numEventsRead; if (ReadConsoleInput(hInput, &inputRecord, 1, &numEventsRead)) { if (inputRecord.EventType == KEY_EVENT && inputRecord.Event.KeyEvent.bKeyDown) { WORD vkCode = inputRecord.Event.KeyEvent.wVirtualKeyCode; if (vkCode == VK_ESCAPE) { SetConsoleMode(hInput, prevMode); return "ESC"; } if (vkCode == VK_UP) { SetConsoleMode(hInput, prevMode); return "↑"; } if (vkCode == VK_DOWN) { SetConsoleMode(hInput, prevMode); return "↓"; } if (vkCode == VK_LEFT) { SetConsoleMode(hInput, prevMode); return "←"; } if (vkCode == VK_RIGHT) { SetConsoleMode(hInput, prevMode); return "→"; } if (vkCode == VK_RETURN) { SetConsoleMode(hInput, prevMode); return "ENTER"; } CHAR asciiChar = inputRecord.Event.KeyEvent.uChar.AsciiChar; if (asciiChar > 0 && !std::iscntrl(asciiChar)) { SetConsoleMode(hInput, prevMode); return str(1, asciiChar); } } } } } class ColorStr { private: str outputStr; WORD textColor; WORD originalAttr; WORD ParseColor(const str& colorStr) const { if (colorStr.empty()) return 0x07; try { size_t pos = 0; int value = std::stoi(colorStr, &pos, 16); if (pos == colorStr.size()) { return static_cast<WORD>(value & 0xFF); } } catch (...) {} return 0x07; } public: ColorStr() : textColor(0x07), originalAttr(0x07) { outputStr = " "; } void SetStr(const str& b) { outputStr = b; } str GetStr() const { return outputStr; } void SetColor(const str& a) { textColor = ParseColor(a); } void print() { HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csbi; if (GetConsoleScreenBufferInfo(hConsole, &csbi)) { originalAttr = csbi.wAttributes; } else { originalAttr = 0x07; } SetConsoleTextAttribute(hConsole, textColor); std::cout << outputStr; SetConsoleTextAttribute(hConsole, originalAttr); std::cout.flush(); } }; template <typename Describe, typename Value> class data_list { using Descr = Describe; using pdv = std::pair<Descr, Value>; std::map<Descr, Value> data; public: data_list() {} ~data_list() {} void add(Descr des, Value val) { data.insert({ des, val }); } void erase(Descr des) { data.erase(des); } void print() { for (auto i : data) { std::cout << i.first << ' ' << i.second << std::endl; } } size_t size() { return data.size(); } void print(Descr idx) { if (data.empty()) return; std::cout << idx << ':' << data[idx] << std::endl; } Value& operator[](Descr idx) { return data[idx]; } operator std::vector<pdv>() { std::vector<pdv> temp; for (const auto& p : data) { temp.push_back(p); } return temp; } auto begin() { return data.begin(); } auto end() { return data.end(); } }; class screen { using vcc = std::vector<std::vector>; vcc scr; size_t n, m; data_list<str, int> data; public: screen(size_t n_, size_t m_) : n(n_), m(m_) { vcc temp(n, std::vector(m)); for (auto& row : temp) { for (auto& cell : row) { cell.SetStr(" "); cell.SetColor(“F0”); } } scr = temp; } int& Data(str des) { return data[des]; } void add(str des, int val) { data.add(des, val); } void erase(str des) { data.erase(des); } void print() { ColorStr border; border.SetColor("F1"); border.SetStr("+"); border.print(); for (size_t i = 0; i < m; i++) { border.SetStr("-"); border.print(); } border.SetStr("+\n"); border.print(); for (auto& row : scr) { border.SetStr("|"); border.print(); for (auto& cell : row) { cell.print(); } border.SetStr("|\n"); border.print(); } border.SetStr("+"); border.print(); for (size_t i = 0; i < m; i++) { border.SetStr("-"); border.print(); } border.SetStr("+\n"); border.print(); data.print(); } std::vector<ColorStr>& operator[](int idx) { return scr[idx]; } auto begin() { return scr.data(); } auto end() { return scr.data() + n; } size_t x_size() { return n; } size_t y_size() { return m; } }; class role { public: role(screen& screen_) : scr(screen_) { role_count++; } virtual ~role() { role_count–; } virtual void operator=(const role& oth) { scr = oth.scr; } protected: screen& scr; }; class apple : public role { int x_, y_; public: apple(screen& screen_) : role(screen_) { regenerate(); } void regenerate() { int sx = scr.x_size(), sy = scr.y_size(); do { x_ = ran(0, sx - 1); y_ = ran(0, sy - 1); } while (scr[x_][y_].GetStr() != " "); } void update() { scr[x_][y_].SetStr("c"); scr[x_][y_].SetColor("F4"); } int x() { return x_; } int y() { return y_; } }; class snack : public role { std::queue sna; apple& app; int dirx, diry; str name, current_dir; bool died, IsRobot; str color_code; void calculate_safe_direction(int x, int y) { int sx = scr.x_size(); int sy = scr.y_size(); std::vector<int> distances = { y, sy - 1 - y, x, sx - 1 - x }; int max_index = std::max_element(distances.begin(), distances.end()) - distances.begin(); switch (max_index) { case 0: dirx = 0; diry = -1; current_dir = "←"; break; case 1: dirx = 0; diry = 1; current_dir = "→"; break; case 2: dirx = -1; diry = 0; current_dir = "↑"; break; case 3: dirx = 1; diry = 0; current_dir = "↓"; break; } } int dis(int ax, int ay, int bx, int by) { return std::abs(ax - bx) + std::abs(ay - by); } public: explicit snack(screen& screen_, apple& apple_, str name_, int x, int y, bool IsPlayer = false) : role(screen_), app(apple_), name(name_), died(false), IsRobot(!IsPlayer) { dirx = diry = 0; int sx = scr.x_size(), sy = scr.y_size(); if (x < 0) throw std::out_of_range(“x<0”); if (y < 0) throw std::out_of_range(“y<0”); if (x >= sx) throw std::out_of_range(“x>=screen_x”); if (y >= sy) throw std::out_of_range(“y>=screen_y”); if (name_ == "Robot_A") { color_code = "F3"; } else if (name_ == "Robot_B"){ color_code = "F5"; } else { color_code = "F2"; } sna.push({ x, y }); scr[x][y].SetStr("o"); scr[x][y].SetColor(color_code); scr.add(name_, 0); snack_count++; calculate_safe_direction(x, y); } ~snack() { scr.erase(name); } void die() { size_t sz = sna.size(); for (size_t i = 0; i < sz; i++) { PII f = sna.front(); sna.pop(); scr[f.first][f.second].SetStr("o"); scr[f.first][f.second].SetColor("F8"); sna.push(f); } snack_count--; died = true; throw std::runtime_error(name + "死了\n总长度达到:" + std::to_string(scr.Data(name) + 1) + '\n'); } void ChangeDir(str new_dir) { if (new_dir == "↑" && (dirx != 1 || IsRobot)) { dirx = -1; diry = 0; current_dir = "↑"; } else if (new_dir == "↓" && (dirx != -1 || IsRobot)) { dirx = 1; diry = 0; current_dir = "↓"; } else if (new_dir == "←" && (diry != 1 || IsRobot)) { dirx = 0; diry = -1; current_dir = "←"; } else if (new_dir == "→" && (diry != -1 || IsRobot)) { dirx = 0; diry = 1; current_dir = "→"; } else if (new_dir != "" && !IsRobot) throw std::invalid_argument("错误的方向参数:" + new_dir); } void UpDate(bool Auto = true) { if (died) return; if (IsRobot && Auto) { std::vector<std::tuple<str, int, int >> directions = { {"↑", -1, 0}, {"↓", 1, 0}, {"←", 0, -1}, {"→", 0, 1} }; str opposite_dir; if (current_dir == "↑") opposite_dir = "↓"; else if (current_dir == "↓") opposite_dir = "↑"; else if (current_dir == "←") opposite_dir = "→"; else opposite_dir = "←"; auto& head = sna.back(); int ax = app.x(), ay = app.y(); int best_dist = INT_MAX; str best_dir = current_dir; bool found_safe_move = false; for (const auto& [dir, dx, dy] : directions) { if (dir == opposite_dir) continue; int nx = head.first + dx; int ny = head.second + dy; if (nx < 0 || ny < 0 || nx >= static_cast<int>(scr.x_size()) || ny >= static_cast<int>(scr.y_size())) continue; if (scr[nx][ny].GetStr() != " " && scr[nx][ny].GetStr() != "c") continue; int dist = dis(ax, ay, nx, ny); if (dist < best_dist || (dist == best_dist && dir == current_dir)) { best_dist = dist; best_dir = dir; found_safe_move = true; } } if (found_safe_move) { ChangeDir(best_dir); } } auto head = sna.back(); int nx = head.first + dirx; int ny = head.second + diry; if (nx < 0 || ny < 0 || nx >= static_cast<int>(scr.x_size()) || ny >= static_cast<int>(scr.y_size())) die(); if (scr[nx][ny].GetStr() != " " && scr[nx][ny].GetStr() != "c") die(); if (scr[nx][ny].GetStr() == "c") { app.regenerate(); scr.Data(name)++; } else { PII tail = sna.front(); sna.pop(); scr[tail.first][tail.second].SetStr(" "); scr[tail.first][tail.second].SetColor("F0"); } sna.push({ nx, ny }); scr[nx][ny].SetStr("o"); scr[nx][ny].SetColor(color_code); } }; str filename = “snack.data”; data_list<str, int> score_list; void run_snack() { clear(); str name; std::printf("请输入蛇的名字:"); std::cin >> name; screen scr(20, 20); apple app(scr); int x, y; std::map<int, bool> IsX, IsY; x = ran(0, 19), y = ran(0, 19); bool isquit = name == "ooseven"; snack PlayerSnack(scr, app, name, x, y, !isquit); IsX[x] = true, IsY[y] = true; x = ran(0, 19); while (!IsX[x]) x = ran(0, 19); y = ran(0, 19); while (!IsY[y]) y = ran(0, 19); snack RobotSnackA(scr, app, "Robot_A", x, y, false); IsX[x] = true, IsY[y] = true; x = ran(0, 19); while (!IsX[x]) x = ran(0, 19); y = ran(0, 19); while (!IsY[y]) y = ran(0, 19); snack RobotSnackB(scr, app, "Robot_B", x, y, false); IsX[x] = true, IsY[y] = true; wait_key(); clear(); if (isquit) { while (true) { try { clear(); std::string key = get_key(100); if (key == "ESC") { scr.print(); std::printf("\n游戏暂停中(按回车键继续,ESC键退出本局游戏)……\n"); std::fflush(stdout); str key = get_key(10); while (key != "ENTER" && key != "ESC") { wait(0.01); key = get_key(10); } if (key == "ESC") { clear(); throw std::runtime_error(name + "中途退出了\n总长度达到:" + std::to_string(scr.Data(name) + 1) + '\n'); } } if (key == "\0") { PlayerSnack.UpDate(); } else { PlayerSnack.ChangeDir(key); PlayerSnack.UpDate(false); } RobotSnackA.UpDate(); RobotSnackB.UpDate(); app.update(); scr.print(); wait(0.5); } catch (const std::exception& e) { str temp = e.what(); bool equal = true; for (int i = 0; i < static_cast<int>(name.size()); i++) { if (temp[i] != name[i]) { equal = false; break; } } if (equal) { score_list[name] = std::max(score_list[name], scr.Data(name)); std::printf("游戏结束:\n%s\n", temp.c_str()); std::printf("当前最高分:%d\n", score_list[name]); std::printf("----------------积分列表-----------------\n"); std::printf("玩家\t\t最高分\n"); using psi = std::pair<str, int>; std::vector<psi> temp_list = score_list; std::stable_sort(temp_list.begin(), temp_list.end(), [](const psi& a, const psi& b) { return a.second > b.second; }); for (auto& i : temp_list) { std::printf("%-20s\t\t%d\n", i.first.c_str(), i.second); } std::cout << "-----------------------------------------" << std::endl; wait_key(); break; } } } } else { while (true) { try { clear(); std::string key = get_key(100); if (key == "ESC") { scr.print(); std::printf("\n游戏暂停中(按回车键继续,ESC键退出本局游戏)……\n"); std::fflush(stdout); str key = get_key(10); while (key != "ENTER" && key != "ESC") { wait(0.01); key = get_key(10); } if (key == "ESC") { clear(); throw std::runtime_error(name + "中途退出了\n总长度达到:" + std::to_string(scr.Data(name) + 1) + '\n'); } } PlayerSnack.ChangeDir(key); PlayerSnack.UpDate(); RobotSnackA.UpDate(); RobotSnackB.UpDate(); app.update(); scr.print(); wait(0.5); } catch (const std::exception& e) { str temp = e.what(); bool equal = true; for (int i = 0; i < static_cast<int>(name.size()); i++) { if (temp[i] != name[i]) { equal = false; break; } } if (equal) { score_list[name] = std::max(score_list[name], scr.Data(name)); std::printf("游戏结束:\n%s\n", temp.c_str()); std::printf("当前最高分:%d\n", score_list[name]); std::printf("----------------积分列表-----------------\n"); std::printf("玩家\t\t最高分\n"); using psi = std::pair<str, int>; std::vector<psi> temp_list = score_list; std::stable_sort(temp_list.begin(), temp_list.end(), [](const psi& a, const psi& b) { return a.second > b.second; }); for (auto& i : temp_list) { std::printf("%-20s\t\t%d\n", i.first.c_str(), i.second); } std::cout << "-----------------------------------------" << std::endl; wait_key(); break; } } } } } void start() { clear(); score_list = data_list<str, int>(); if (!std::filesystem::exists(filename)) { std::printf("未找到存档文件 %s\n", filename.c_str()); wait(0.5); clear(); return; } std::ifstream fin(filename); if (!fin.is_open()) { std::printf("打开文件失败\n"); wait(0.5); clear(); return; } std::string header; std::getline(fin, header); if (header != "~") { std::printf("无效文件格式! 期望'~',实际'%s'\n", header.c_str()); fin.close(); wait(0.5); clear(); return; } int seed, salt, res; fin >> seed >> salt >> res; fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); int calculated = (seed * 997 + salt) % 10000; if (calculated != res) { std::printf("存档校验失败! 计算值:%d 文件值:%d\n", calculated, res); fin.close(); wait(0.5); clear(); return; } int record_count; fin >> record_count; fin.ignore(); for (int i = 0; i < record_count; ++i) { std::string name; int score; std::getline(fin, name); fin >> score; fin.ignore(); if (fin.fail()) { std::cerr << "读取分数失败,记录索引: " << i << std::endl; break; } score_list.add(name, score); } fin.close(); std::printf("成功读取 %d 条记录\n", record_count); wait(1); clear(); } void end() { clear(); std::ofstream fout(filename); if (!fout.is_open()) { std::printf("创建文件失败\n"); wait(0.5); clear(); return; } fout << "~\n"; int seed = ran(1, 256); int salt = ran(1000, 9999); int res = (seed * 997 + salt) % 10000; fout << seed << ' ' << salt << ' ' << res << std::endl; fout << score_list.size() << std::endl; for (auto& i : score_list) { fout << i.first << '\n' << i.second << std::endl; } fout.flush(); fout.close(); std::printf("保存完毕\n"); wait(0.5); clear(); wait_key(); clear(); } void launch_snack() { start(); char go = ‘T’; while (go == 'T' || go == 't') { clear(); run_snack(); std::printf("再来一次(T/t)? 输入其他则退出:"); std::cin >> go; } end(); return; }
10-19
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值