• 实验3 类和对象 小球游戏,三角形,分数类


    开幕雷击:本文非常非常非常长,请做好心理准备再阅读!推荐跳过小球游戏,直接阅读分数类的实现!可以直接点击右侧列表实现跳转。

    实验结论

    小球移动游戏

    代码极其垃圾,写法极其鬼畜,阅读前请做好准备。正确的写法应该是再写一个类控制小球的移动,但是我当时一时脑抽,写出了如下产物。切勿模仿!!!!!!!!!

    源码

    main.cpp
    #include <iostream>
    #include <random>
    #include <conio.h>
    #include "canvas.h"
    #include <ctime>
    
    using namespace std;
    
    mt19937 gen(static_cast<unsigned int>(time(nullptr)));
    
    int main() {
        int score=0;
        cout << "Press any key to start,'Q' to quit." << endl;
        if (getch() == 'q' || getch() == 'Q')
            return 0;
        Canvas canvas1("0", "A", 25, 25);
    
        uniform_int_distribution<> enemyX(1, canvas1.getX());
        uniform_int_distribution<> enemyY(1, canvas1.getY());
    
        canvas1.generateBalls(1, 1);
        canvas1.generateBalls(enemyX(gen), enemyY(gen),'$');
        while (true) {
            switch (getch()) {
                case 'W':
                case 'w':
                    canvas1.getBalls()[0].up();
                    canvas1.refreshBalls();
                    break;
                case 'A':
                case 'a':
                    canvas1.getBalls()[0].left();
                    canvas1.refreshBalls();
                    break;
                case 'S':
                case 's':
                    canvas1.getBalls()[0].down();
                    canvas1.refreshBalls();
                    break;
                case 'D':
                case 'd':
                    canvas1.getBalls()[0].right();
                    canvas1.refreshBalls();
                    break;
                case 'Q':
                case 'q':
                    return 0;
            }
            if (canvas1.getBalls()[0].getx() == canvas1.getBalls()[1].getx() &&
                canvas1.getBalls()[0].gety() == canvas1.getBalls()[1].gety()) {
                score++;
                canvas1.deleteLastBall();
                canvas1.generateBalls(enemyX(gen), enemyY(gen),'$');
                canvas1.refreshBalls();
            }
            cout<<"Score:"<<score<<endl;
        }
    }
    
    canvas.h
    #ifndef CANVAS_H
    #define CANVAS_H
    
    #include <vector>
    #include <string>
    #include "ball.h"
    
    using std::string;
    using std::vector;
    
    class Canvas {
    public:
        Canvas(string bg0 = "0", string fg0 = "A", int x = 50, int y = 50);
        void changeCanvasBg(string &bg0);
        void changeCanvasFg(string &fg0);
        void changeCanvasColor(string &bg0, string &fg0);
        void refreshG();
        void refreshBalls();
        void generateBalls(int x0, int y0, char ch0='o');
        void deleteLastBall();
        vector<Ball>& getBalls();
        int getX() const;
        int getY() const;
    
    private:
        int X;
        int Y;
        char **blocks;
        string bg;
        string fg;
        vector<Ball> balls;
    };
    
    #endif
    
    
    canvas.cpp
    #include <utility>
    #include "canvas.h"
    #include <cstdlib>
    #include <iostream>
    
    Ball ball(1, 1, 1, 1);
    
    Canvas::Canvas(string bg0, string fg0, int x, int y) : bg(std::move(bg0)), fg(std::move(fg0)), X(x), Y(y) {
        blocks = new char *[Y];
        for (int i = 0; i < Y; ++i) {
            blocks[i] = new char[X]{' '};
        }
        refreshG();
    }
    
    void Canvas::changeCanvasBg(string &bg0) {
        bg = bg0; // 更新画布背景色
        refreshG();
    
    }
    
    void Canvas::changeCanvasFg(string &fg0) {
        fg = fg0; // 更新画布前景色
        refreshG();
    }
    
    void Canvas::changeCanvasColor(string &bg0, string &fg0) {
        bg = bg0;  // 更新画布背景色
        fg = fg0;   // 更新画布前景色
        refreshG();
    }
    
    void Canvas::refreshG() {
        string color = "color ";
        color += bg;
        color += fg;
        system(color.c_str());
    }
    
    void Canvas::refreshBalls() {
        system("cls");
        for (int j = 0; j < Y; ++j) {
            for (int i = 0; i < X; ++i) {
                blocks[j][i]=' ';
            }
        }
        for (int i = 0; i < balls.size(); ++i) {
            blocks[balls[i].gety()-1][balls[i].getx()-1]=balls[i].getCh();
        }
        for (int j = 0; j < Y; ++j) {
            for (int i = 0; i < X; ++i) {
                std::cout<<blocks[j][i];
            }
            std::cout<<std::endl;
        }
    }
    
    void Canvas::generateBalls(int x0, int y0,char ch0) {
        balls.push_back(ball);
        balls.back().setX(X);
        balls.back().setY(Y);
        balls.back().setx(x0);
        balls.back().sety(y0);
        balls.back().setCh(ch0);
    }
    
    vector<Ball>& Canvas::getBalls() {
        return balls;
    }
    
    int Canvas::getX() const {
        return X;
    }
    
    int Canvas::getY() const {
        return Y;
    }
    
    void Canvas::deleteLastBall() {
        balls.pop_back();
    }
    
    ball.h
    #ifndef BALL_H
    #define BALL_H
    
    class Ball {
    public:
        Ball(int x0, int y0, int X0, int Y0);   // 在坐标(X,Y)处构造一个小球(小球用字符O表示)
        void left(int step = 1);    // 左移step
        void right(int step = 1);        // 右移step
        void up(int step = 1);        // 上移step
        void down(int step = 1);        // 下移step
        void setx(int x0);
        void sety(int y0);
        void setX(int X0);
        void setY(int Y0);
        int getX() const;
        int getY() const;
        int gety() const;
        int getx() const;
        char getCh() const;
        void setCh(char ch='o');
    
    private:
        char ch;
        int x;
        int y;
        int X;
        int Y;
    };
    
    #endif
    
    ball.cpp
    #include "ball.h"
    #include "canvas.h"
    #include <iostream>
    
    using std::cout;
    using std::endl;
    
    Ball::Ball(int x0, int y0, int X0, int Y0) : x(x0), y(y0), X(X0), Y(Y0) {
    }
    
    void Ball::left(int step) {
        x = x - step;
        if (x <= 1)
            x = 1;
    }
    
    void Ball::right(int step) {
        x = x + step;
        if (x >= X)
            x = X;
    }
    
    void Ball::up(int step) {
        y = y - step;
        if (y <= 1)
            y = 1;
    }
    
    void Ball::down(int step) {
        y = y + step;
        if (y >= Y)
            y = Y;
    }
    
    void Ball::setY(int Y0) {
        Y = Y0;
    }
    
    void Ball::setx(int x0) {
        x = x0;
    }
    
    void Ball::sety(int y0) {
        y = y0;
    }
    
    void Ball::setX(int X0) {
        X = X0;
    }
    
    int Ball::getx() const {
        return x;
    }
    
    int Ball::gety() const {
        return y;
    }
    
    int Ball::getX() const {
        return X;
    }
    
    int Ball::getY() const {
        return Y;
    }
    
    void Ball::setCh(char ch0) {
        ch = ch0;
    }
    
    char Ball::getCh() const {
        return ch;
    }
    

    运行截图

    画三角形

    因为上一part里已经做过控制小球移动的内容了,本part的实现基本一样,所以咕咕咕了也没什么问题吧。(笑

    源码

    main.cpp
    #include <iostream>
    #include "graph.h"
    
    using namespace std;
    
    int main() {
        Graph graph1('*', 5);
        graph1.draw();
        Graph graph2('$', 7);
        graph2.draw();
        cin.get();
        return 0;
    }
    
    graph.h
    #ifndef GRAPH_H
    #define GRAPH_H
    
    // 类Graph的声明 
    class Graph {
    public:
        Graph(char ch, int n);   // 带有参数的构造函数
        void draw();    // 绘制图形
    private:
        char symbol;
        int size;
    };
    
    #endif
    
    graph.cpp
    // 类graph的实现
    
    #include "graph.h"
    #include <iostream>
    
    using namespace std;
    
    // 带参数的构造函数的实现 
    Graph::Graph(char ch, int n) : symbol(ch), size(n) {
    }
    
    // 成员函数draw()的实现
    // 功能:绘制size行,显示字符为symbol的指定图形样式 
    void Graph::draw() {
        for (int i = 0; i < size; ++i) {
            for (int j = 0; j < size - i - 1; ++j) {
                cout << ' ';
            }
            for (int k = 0; k < 2 * (i + 1) - 1; k++) {
                cout << symbol;
            }
            cout << endl;
        }
    }
    

    运行截图

    Fraction类的实现

    源码

    main.cpp
    #include <iostream>
    #include "Fraction.h"
    
    using namespace std;
    
    int main() {
        Fraction a(-1, 2);
        Fraction b(4, -3);
        Fraction c(-5, -20);
        Fraction d(5, 1);
        Fraction e(1, -5);
        a.show();
        cout << a << endl;
        cout << a.add(b) << endl;
        cout << a + b << endl;
        cout << b.minus(c) << endl;
        cout << b - c << endl;
        cout << c.multiply(d) << endl;
        cout << c * d << endl;
        cout << d.division(e) << endl;
        cout << d / e << endl;
        cout << d.compare(e) << endl;
        cout << d.compare(d) << endl;
        cout << e.compare(d) << endl;
        return 0;
    }
    
    Fraction.h
    //
    // Created by KOKODA on 2019/4/21.
    //
    
    #ifndef FRACTION_H
    #define FRACTION_H
    
    #include<iostream>
    
    class Fraction {
    private:
        int top;
        int bottom;
    public:
        Fraction(int top = 0, int bottom = 1);
        Fraction add(Fraction &a);
        Fraction minus(Fraction &a);
        Fraction multiply(Fraction &a);
        Fraction division(Fraction &a);
        Fraction operator*(Fraction &a);
        Fraction operator+(Fraction &a);
        Fraction operator-(Fraction &a);
        Fraction operator/(Fraction &a);
        int compare(Fraction &a);
        friend std::ostream& operator << (std::ostream&,Fraction);
        void show();
        double Decimal();
    };
    #endif //FRACTION_H
    
    Fraction.cpp
    //
    // Created by KOKODA on 2019/4/21.
    //
    
    #include "Fraction.h"
    #include <iostream>
    
    int gcd(int a0, int b0) {
        int a = std::abs(a0);
        int b = std::abs(b0);
        if (a < b) {
            std::swap(a, b);
        }
        if (b == 0) {
            return a;
        } else {
            return gcd(b, a % b);
        }
    }
    
    int lcm(int a, int b) {
        return std::abs(a * b) / gcd(a, b);
    }
    
    Fraction::Fraction(int top0, int bottom0) : top(top0 / gcd(top0, bottom0)), bottom(bottom0 / gcd(top0, bottom0)) {
        if (top * bottom > 0) {
            top = abs(top);
            bottom = abs(bottom);
        } else if (bottom < 0) {
            top = -top;
            bottom = -bottom;
        }
    }
    
    Fraction Fraction::operator+(Fraction &a) {
        return {top * (lcm(bottom, a.bottom) / bottom) + a.top * (lcm(bottom, a.bottom) / a.bottom), lcm(bottom, a.bottom)};
    }
    
    Fraction Fraction::add(Fraction &a) {
        return {top * (lcm(bottom, a.bottom) / bottom) + a.top * (lcm(bottom, a.bottom) / a.bottom), lcm(bottom, a.bottom)};
    }
    
    Fraction Fraction::operator-(Fraction &a) {
        return {top * (lcm(bottom, a.bottom) / bottom) - a.top * (lcm(bottom, a.bottom) / a.bottom), lcm(bottom, a.bottom)};
    }
    
    Fraction Fraction::minus(Fraction &a) {
        return {top * (lcm(bottom, a.bottom) / bottom) - a.top * (lcm(bottom, a.bottom) / a.bottom), lcm(bottom, a.bottom)};
    }
    
    Fraction Fraction::operator*(Fraction &a) {
        return {top * a.top, bottom * a.bottom};
    }
    
    Fraction Fraction::multiply(Fraction &a) {
        return {top * a.top, bottom * a.bottom};
    }
    
    Fraction Fraction::operator/(Fraction &a) {
        return {top * a.bottom, bottom * a.top};
    }
    
    Fraction Fraction::division(Fraction &a) {
        return {top * a.bottom, bottom * a.top};
    }
    
    void Fraction::show() {
        if (top / bottom == (double) top / (double) bottom)
            std::cout << top / bottom << std::endl;
        else
            std::cout << top << '/' << bottom << std::endl;
    }
    
    std::ostream &operator<<(std::ostream &output, Fraction a) {
        if (a.top / a.bottom == (double) a.top / (double) a.bottom)
            output << a.top / a.bottom;
        else
            output << a.top << '/' << a.bottom;
        return output;
    }
    
    double Fraction::Decimal() {
        return (double) top / (double) bottom;
    }
    
    int Fraction::compare(Fraction &a) {
        if(((*this)-a).bottom*((*this)-a).top<0)
            return -1;
        else if(((*this)-a).bottom*((*this)-a).top==0)
            return 0;
        else
            return 1;
    }
    

    运行截图

    实验总结与体会

    part1

    这一part的话,正确的做法是使用一个新的类来控制小球的移动,但是因为我当时没想到而且我就想用给的两个类来着,于是写了这么个不伦不类的东西,总之大家不要学我。但还是基本写出了个框架可以实现多个小球同台竞技了,加球也还算简单吧(心虚。

    part2

    找出公式就好了,没什么说的。

    part3

    最最最重要的部分来了,分数类的设计用到了运算符重载,不过这不关键,主要是在构造函数的设计上我采用了将输入直接约分的形式,保证所有分数类对象在创建的时候是以最简形式出现的,然后在进行 +-*/ 的运算时,返回值时会调用构造函数,也就保证了所有运算得出的值都是最简形式,计划通!完美,这样做得话不但完美解决了最简形式的问题,而且代码简洁又工整,看起来很舒服。那么说完了最关键的部分,我来提一手分数类实现的功能。

    1. 实现了 add()minus()multiply()division()函数用以进行加减乘除运算。
    2. 运用运算符重载实现分数类对象使用 +-*/运算符进行运算。
    3. 实现了返回分数对应的小数值的函数
    4. 实现了两个分数的比较 例:a.compare(b)若a > b则返回1,a = b则返回0,a < b则返回-1

    值得一提的是 compare()的实现我使用了this指针这样就可以利用之前实现的-运算符重载直接比较两者的大小

    ps:也可以直接重载> <号来实现直接比较,但我就没有去做了,有兴趣的同学可以试着写写看。

  • 相关阅读:
    为什么在SqlServer流水模式下,事务无法启动?
    默认web站点被删除,如何设置新的默认站点?
    用C#实现基于TCP协议的网络通讯
    如何通过DataRelation关联两个DataGrid,实现主从表。
    如何设置网站的会话时间?
    性能测试基本概念释疑
    C#中如何获取服务器IP,名称,操作系统,客户端IP,名称!
    DataGridComboBoxColumn控件
    端口基础知识
    P2P之UDP穿透NAT的原理与实现
  • 原文地址:https://www.cnblogs.com/KOKODA/p/10749482.html
Copyright © 2020-2023  润新知