// Today's class code 3/11
// We are going to code a game called Dead Ringer
// In this game, we will randomly generate one of two things:
// 1. A linked list of 2000 (suitable large number) nodes
// 2. A ring of some small number of nodes (eg. 20)
// Now, we will present this structure starting at the first node
// using our animate list method*
// Now, we will ask the user:
// Are the above numbers part of a list (L), a ring (R), or do you
// want to scroll (S)?
// If the user guessed right, go to the next level with a slightly
// larger ring size.
// If they want to scroll, then scroll once using our animate
// function and loop back to our question
// When the round ends, present stats like the total amount of time
// taken and number of times they had to scroll
// If they get it wrong, we will break out of the loop and end the
// game.
// Modification to the animate list function
// This function will h-scroll the list with steadily increasing
// sleep times so it will look like it is slowing down
// When it is too slow, it will return the left most printed
#include <iostream>
#include <unistd.h>
#include <cstdlib> // For rand()
using namespace std;
// Node structure
struct Node {
int _data;
Node *_next;
Node(int d = 0, Node *p = nullptr) : _data(d), _next(p) {}
};
class Int_List {
private:
Node *_first_node;
public:
Int_List(Node *p = nullptr) : _first_node(p) {}
void insert_at_beginning(int n);
void insert_at_end(int n);
void insert_after(Node *p, int n);
string to_string() const;
void animate_list();
void cout_list() const;
};
// Insert at the beginning
void Int_List::insert_at_beginning(int n){
Node *p = new Node(n);
p->_next = _first_node;
_first_node = p;
}
// Insert at the end
void Int_List::insert_at_end(int n) {
Node *new_node = new Node(n);
if (_first_node == nullptr) {
_first_node = new_node;
return;
}
Node *p = _first_node;
while (p->_next != nullptr) {
p = p->_next;
}
p->_next = new_node;
}
// Insert after a given node
void Int_List::insert_after(Node *p, int n) {
if (p == nullptr) return;
Node *new_node = new Node(n,p->_next);
p->_next = new_node;
}
// Convert list to string
string Int_List::to_string() const {
string result;
for (Node *p = _first_node; p != nullptr; p = p->_next) {
result += std::to_string(p->_data) + " -> ";
}
return result + "END";
}
// Print the list
void Int_List::cout_list() const {
for (Node *p = _first_node; p != nullptr; p = p->_next)
cout << p->_data << " ";
cout << "End" << endl;
}
// ----------------------------------------------------
// The following is a global function outside the class
// Print up to 30 nodes, fix infinite loop issue
void show_nodes(Node *nodeP) {
int n = 0;
Node *p = nodeP;
while (p != nullptr) {
cout << p->_data << " ";
p = p->_next; // Move to next node
if (n++ > 30) break;
}
cout << (p == nullptr ? "END" : "...") << " \r" << flush;
}
void Int_List::animate_list() {
int n = 0;
for (Node *p = _first_node; p != nullptr; p = p->_next) {
show_nodes(p);
if (n++ > 100) break;
usleep(500 * 1000); // 500ms delay
}
}
// This function will show a horizontal scrolling animation of a
// linked list of nodes starting at nodeP with gradually slowing
// down animation and returning the left most node when it gets too
// slow
Node *h_scroll(Node *nodeP) {
// This is the factor by which the sleep time increases after
// each h_scroll effect
double slow_down_rate = 1.05;
size_t max_display_len = 30;
double sleep_time = 500.0; // Initial sleep time
Node *p;
while(sleep_time < 1000*1000){
size_t n = 0;
for(p = nodeP; p != nullptr; p = p->_next){
cout << " " << p->_data;
if (n++ > max_display_len) break;
}
if(p == nullptr)
cout << "END";
cout << "\r" << flush;
usleep((size_t) sleep_time);
sleep_time *= slow_down_rate;
nodeP = nodeP->_next;
}
return nodeP;
}
int main(){
srand((unsigned) time(nullptr));
Node *p = new Node(0, nullptr);
// Create a chain of a 100 nodes starting at p
Node *q = p;
for(size_t i = 1; i <= 100; i++)
q = new Node(i, q);
// At this point, q will be the last node inserted, starting a
// chain that ends at the first node p;
h_scroll(q);
// Node *p;
// size_t ring_size = 15, list_size = 2000;
// bool is_a_list;
// if(rand() % 2 == 0){
// p = get_ring(ring_size);
// is_a_list = false;
// }else{
// p = get_list(list_size);
// is_a_list = true;
// }
// size_t num_scrolls = 0;
return 0;
}