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

posted @ 2019-04-22 12:41  KOKODA  阅读(349)  评论(2编辑  收藏  举报